Subject: [clisp-list] Still more on the FFI issue

From: Fred Cohen <[email-masked]>
Date: Fri Sep 12 12:23:38 2003

I have now tested the FFI interface using the code and example for
vector.o provided with the slisp documentation, and it also failed.
This is not good...

It looks like call-rawsock.c which was autogenerated from
call-rawsock.lisp doesn't generate some header information -

#include "clisp.h"

extern object module__call_rawsock__object_tab[];

subr_t module__call_rawsock__subr_tab[1];
uintC module__call_rawsock__subr_tab_size = 0;
subr_initdata_t module__call_rawsock__subr_tab_initdata[1];

object module__call_rawsock__object_tab[1];
object_initdata_t module__call_rawsock__object_tab_initdata[1];
uintC module__call_rawsock__object_tab_size = 0;

void module__call_rawsock__init_function_1 (module_t* module)
{ }

void module__call_rawsock__init_function_2 (module_t* module)
{
  register_foreign_variable((void*)&buffer,"buffer",0,sizeof(buffer));
  register_foreign_variable((void*)&from,"from",0,sizeof(from));
  register_foreign_variable((void*)&f,"f",0,sizeof(f));
...

The errors come because there is no function defined prior to these
register things.  Since the Raw Socket Interface (which I am trying to
compile) is provided for all to use, I figure including it here will
help to debug this problem in moving it from clisp-2.27 to clisp-2.31.
Appologies if this is too long:

The program that builds it (or did under the older clisp version):
base=/usr/local/lib/clisp/base;export base
rm -rf ${base}/rawsock
export CLISP_LINKKIT=/usr/local/lib/clisp/linkkit/
rm -rf call-rawsock.c call-rawsock.fas call-rawsock.lib rawsock
/usr/local/lib/clisp/clisp-link create-module-set rawsock call-rawsock.c
cc -O -c rawsock.c
cd rawsock
ln -s ../rawsock.o rawsock.o
cp -f ../thingtofix link.sh
cd ..
${base}/lisp.run -M ${base}/lispinit.mem -q -c call-rawsock.lisp

# it works up to here...
/usr/local/lib/clisp/clisp-link add-module-set rawsock ${base} ${base}/rawsock

# and this fails with the error messages indicating that the functions
# and variables from rawsock.c cannot be found.

echo "(exit)" | ${base}/rawsock/lisp.run -q -M ${base}/rawsock/lispinit.mem -i call-rawsock
${base}/rawsock/lisp.run -q -M ${base}/rawsock/lispinit.mem -q -i call-rawsock -c R.lsp -c tg.lsp -c router.lsp
echo "Run with ${base}/rawsock/lisp.run -M ${base}/rawsock/lispinit.mem -i call-rawsock"

=======================================================================
call-rawsock.lisp:
(DEFPACKAGE "RAWSOCK" (:use "LISP" "FFI"))
(IN-PACKAGE "RAWSOCK")

; (setq snaplen 1514)
(def-c-var buffer (:name "buffer") (:type (c-array uchar 1518)) (:read-only nil) (:alloc :none) )
(def-c-struct sockaddr (sa_family short) (sa_data (c-array char 14)))
(def-c-var from (:name "from") (:type sockaddr) (:read-only nil) (:alloc :none))
(def-c-var f (:name "f") (:type (c-array uchar 16)) (:read-only nil) (:alloc :none))
(def-c-var timestamp (:name "timestamp") (:type (c-array uchar 16)) (:read-only t) (:alloc :none))
(def-c-var ts (:name "ts") (:type c-string) (:read-only t) (:alloc :none))

(def-c-call-out rawsocket (:return-type int))
(def-c-call-out closesock (:arguments (s int)) (:return-type int))
(def-c-call-out ipcsum (:return-type ushort))
(def-c-call-out icmpcsum (:return-type ushort))
(def-c-call-out tcpcsum (:return-type ushort))
(def-c-call-out udpcsum (:return-type ushort))
(def-c-call-out recvfr (:arguments (rawsock int)) (:return-type int))
(def-c-call-out sendt (:arguments (rawsock int) (len int)) (:return-type int))
(def-c-call-out gettime (:return-type int))
(def-c-call-out backup (:return-type int))
(def-c-call-out restore (:return-type int))
(def-c-call-out configdev (:arguments (rawsock int) (name c-string)
			(ipadd int) (prom int) (noarp int)) (:return-type int))
(def-c-call-out perror (:arguments (name c-string)))
=======================================================================
rawsock.c:
=======================================================================
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <netinet/if_ether.h>
#include <net/if.h>

#include <sys/ioctl.h>
#define snaplen 1518
#define MAX_DEVICE_NAME_SIZE 14
#define BUFSIZE 2*snaplen
#define ETH_HEAD_LEN    14
#define ARP_HEAD_LEN    28
#define IP_HEAD_LEN     20    /* don't use ----ip varible size use ip->ip_hl = num of 32 bit words */
#define TCP_HEAD_LEN    20    /* don't use ----ip varible size use ip->ip_hl = num of 32 bit words */
#define TCP_HEAD_BASE   (ETH_HEAD_LEN + IP_HEAD_LEN)
#define FIN  0x01
#define SYN  0x02
#define RST  0x04
#define PSH  0x08
#define ACK  0x10
#define URG  0x20

#include <errno.h>
void perror(const char *s);

int device_count;
unsigned char buffer[snaplen], buff[snaplen];
struct sockaddr from, fr;
char *f;
int from_len;
char timestamp[20], *ts=&timestamp[0];
time_t *tloc, t;
char confighw=0;

int rawsocket() {return socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL) );}
int closesock(int s) {return close(s);}

int backup () {memcpy(buff, buffer, sizeof(buff));memcpy( fr, from, sizeof(from));}
int restore () {memcpy(buffer, buff,  sizeof(buff));memcpy(from, fr, sizeof(from));}

int gettime() {t=time(NULL);strftime(timestamp, 20, "%Y/%m/%d %T", localtime(&t));return(0);}
int recvfr(int s) {f=&from;gettime();return(recvfrom(s, buffer, snaplen, 0, &from, &from_len));}
int sendt(int s, unsigned int length) {return(sendto(s, buffer, length, 0, &from,  sizeof(from)));}

int configdev(int s, char *name, int ipadd, int prom, int noarp)
	{struct ifreq ifrequest; register int i,j;
	memset(&ifrequest,  0, sizeof(struct ifreq));
	strcpy(ifrequest.ifr_name, name);
	if (ioctl(s, SIOCGIFFLAGS, &ifrequest) < 0)
		{printf("dev = %s \n", name); perror("SOCKET: get flags ");return -1;}
	if (prom != 0) {ifrequest.ifr_flags |= IFF_PROMISC;}
	if (noarp != 0) {ifrequest.ifr_flags |= IFF_NOARP;}
	if (ioctl(s,  SIOCSIFFLAGS,  &ifrequest) < 0) {perror("SOCKET: setpromisc "); return -1;}
	memset(&ifrequest, 0, sizeof(struct ifreq));
	strcpy(ifrequest.ifr_name, name); /* add was 0.0.0.0 -> err*/
	if (ioctl(s, SIOCGIFADDR, &ifrequest) < 0) {perror("address already 0.0.0.0");}
	if (ipadd != 0) {if (ioctl(s, SIOCGIFADDR, &ifrequest) < 0) {perror("address already 0.0.0.0");}
	else	{for (j=2;j <6;j++) {ifrequest.ifr_addr.sa_data[j] = 0;}
		if (ioctl(s, SIOCSIFADDR,  &ifrequest) < 0) {perror("SOCKET: setadd"); return -1;}
		}
			}
	return 0;}

unsigned short ipcsum() 	       /* IP CHECKSUM */
	{register long sum=0;           /* assumes long == 32 bits */
	unsigned short result;	unsigned char *ptr=&(buffer[14]);int nbytes;
	buffer[24]=0;buffer[25]=0;nbytes=(buffer[14] & 0xF) << 2; /* checksum=0, headerlen */
	while(nbytes>1){sum += *ptr; ptr++; sum += *ptr <<8; ptr++; nbytes -= 2;}
	if(nbytes==1){sum += *ptr;}     /* mop up an odd byte,  if necessary */
	sum = (sum >> 16) + (sum & 0xFFFF);result=~(sum  + (sum >> 16)) & 0xFFFF;
	buffer[24]=(result & 0xFF);buffer[25]=((result >> 8) & 0xFF);return(result);}

unsigned short icmpcsum() 	       /* ICMP CHECKSUM */
	{register long sum=0;           /* assumes long == 32 bits */
	unsigned short result;	unsigned char *ptr;int nbytes, off, offset;
	off=((buffer[14]&0xF)<<2);offset=off+14;		/* start of ICMP header */
	buffer[offset+2]=0;buffer[offset+3]=0;
	nbytes=(((buffer[16])<<8)+(buffer[17]))-off; /* bytes in ICMP part */
	ptr=&(buffer[offset]);
	while(nbytes>1){sum += *ptr; ptr++; sum += *ptr <<8; ptr++; nbytes -= 2;}
	if(nbytes==1){sum += *ptr;}     /* mop up an odd byte,  if necessary */
	sum = (sum >> 16) + (sum & 0xFFFF);result=~(sum  + (sum >> 16)) & 0xFFFF;
	buffer[offset+2]=(result & 0xFF);buffer[offset+3]=((result >> 8) & 0xFF);return(result);}

unsigned short tcpcsum()		/* TCP checksum */
	{register unsigned long sum;  /* assumes long == 32 bits */
	unsigned short result;	unsigned char *ptr;
	unsigned nbytes, packsize, offset;
	sum = (buffer[26]<<8)+ buffer[27]+(buffer[28]<<8)+ buffer[29];	/* Src IP */
	sum +=(buffer[30]<<8)+ buffer[31]+(buffer[32]<<8)+ buffer[33];	/* Dst IP */
	sum +=(buffer[23]);				/* zero followed by protocol */
	packsize=((buffer[16])<<8)+(buffer[17]);	/* packet size - not including ARP area */
	offset=((buffer[14]&0xF)<<2);			/* start of TCP header (rel to IP header) */
	sum +=(packsize - offset);			/* size of TCP part of the packet */
	ptr=&(buffer[offset+14]);			/* start of TCP header in buffer */
	nbytes=packsize-offset;				/* number of bytes to checksum */
	buffer[offset+16+14]=0;buffer[offset+17+14]=0;	/* initialize TCP checksum to 0 */
	while(nbytes>1){sum += *ptr<<8; ptr++; sum += *ptr; ptr++; nbytes -= 2;}
	if(nbytes==1){sum += *ptr<<8;}			/* mop up an odd byte,  if necessary */
	sum = (sum >> 16) + (sum & 0xFFFF);result=~(sum  + (sum >> 16)) & 0xFFFF;
	buffer[offset+17+14]=(result & 0xFF);buffer[offset+16+14]=((result >> 8) & 0xFF);
	return(result);}

unsigned short udpcsum()		/* UDP checksum */
	{register unsigned long sum = 0;  /* assumes long == 32 bits */
	unsigned short result;	unsigned char *ptr;
	int nbytes, packsize, offset;
	sum = (buffer[26]<<8)+ buffer[27]+(buffer[28]<<8)+ buffer[29];	/* Src IP */
	sum +=(buffer[30]<<8)+ buffer[31]+(buffer[32]<<8)+ buffer[33];	/* Dst IP */
	sum +=(buffer[23]);				/* zero followed by protocol */
	packsize=((buffer[16])<<8)+(buffer[17]);		/* packet size */
	offset=((buffer[14]&0xF)<<2);			/* start of UDP header */
	sum +=(((buffer[16])<<8)+(buffer[17])) -offset;
	ptr=&(buffer[offset+14]);	/* start of TCP header */
	nbytes=packsize-offset;
	buffer[offset+6+14]=0;buffer[offset+7+14]=0;	/* initialize UDP checksum to 0 */
	while(nbytes>1){sum += *ptr <<8; ptr++; sum += *ptr; ptr++; nbytes -= 2;}
	if(nbytes==1){sum += *ptr<<8;}			/* mop up an odd byte,  if necessary */
	sum = (sum >> 16) + (sum & 0xFFFF);result=~(sum  + (sum >> 16)) & 0xFFFF;
	buffer[offset+7+14]=(result & 0xFF);buffer[offset+6+14]=((result >> 8) & 0xFF);return(result);}

-- This communication is confidential to the parties it is intended to serve --
Fred Cohen - http://all.net/ - [email-masked] - [email-masked] - tel/fax: 925-454-0171
Fred Cohen & Associates	- University of New Haven - Security Posture