Undefined symbols for architecture i386 for OpenSSL library - c

I'm reading this book Network Security with OpenSSL by Pravir Chandra, Matt Messier and John Viega and I'm trying to create an SSL client/server connection after their example in the book using OpenSSL but I get this error and I don't know why.
This is my server:
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#include <pthread.h>
#define PORT "6001"
#define SERVER "splat.zork.org"
#define CLIENT "shell.zork.org"
void handle_error(const char *file, int lineno, const char *msg)
{
fprintf(stderr, "** %s:%i %s\n", file, lineno, msg);
ERR_print_errors_fp(stderr);
exit(-1);
}
void init_OpenSSL(void)
{
if (!THREAD_setup() || !SSL_library_init())
{
fprintf(stderr, "** OpenSSL initialization failed!\n");
exit(-1);
}
SSL_load_error_strings();
}
void do_server_loop(BIO *conn)
{
int done, err, nread;
char buf[80];
do
{
for (nread = 0; nread < sizeof(buf); nread += err)
{
err = BIO_read(conn, buf + nread, sizeof(buf) - nread);
if (err <= 0)
break;
}
fwrite(buf, 1, nread, stdout);
}
while (err > 0);
}
void *server_thread(void *arg)
{
BIO *client = (BIO *)arg;
pthread_detach(pthread_self( ));
fprintf(stderr, "Connection opened.\n");
do_server_loop(client);
fprintf(stderr, "Connection closed.\n");
BIO_free(client);
ERR_remove_state(0);
}
int main(int argc, char *argv[])
{
BIO *acc, *client;
pthread_t tid;
init_OpenSSL();
acc = BIO_new_accept(PORT);
if (!acc)
handle_error(__FILE__, __LINE__, "Error creating server socket");
if (BIO_do_accept(acc) <= 0)
handle_error(__FILE__, __LINE__, "Error binding server socket");
for (;;)
{
if (BIO_do_accept(acc) <= 0)
handle_error(__FILE__, __LINE__, "Error accepting connection");
client = BIO_pop(acc);
pthread_create(&tid, NULL, server_thread, client);
}
BIO_free(acc);
return 0;
}
I'm compiling the source using gcc:
$ gcc -o server server.c -lssl -crypto -lpthread -lm
Undefined symbols for architecture i386:
"_ERR_print_errors_fp", referenced from:
_handle_error in ccgAll3d.o
"_THREAD_setup", referenced from:
_init_OpenSSL in ccgAll3d.o
"_BIO_read", referenced from:
_do_server_loop in ccgAll3d.o
"_BIO_free", referenced from:
_server_thread in ccgAll3d.o
"_ERR_remove_state", referenced from:
_server_thread in ccgAll3d.o
"_BIO_new_accept", referenced from:
_main in ccgAll3d.o
"_BIO_ctrl", referenced from:
_main in ccgAll3d.o
"_BIO_pop", referenced from:
_main in ccgAll3d.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
Can anyone tell me why is this happening?
I got something similar some time ago and solved it by defining the functions that were problematic but this doesn't work anymore.
I'm compiling the source on a Mac OS X 10.6.8.
Is it because I'm using a 32-bit system?
This is the command I'm compiling with gcc -Wall -lssl -crypto -lpthread -lm -o server server.c

You'll be a little closer with gcc -o server sslserver.c -pthread -lssl.
Also the book's errata inform us that SSL_init_library should be SSL_library_init.
The only undefined reference left is 'THREAD_setup'.

You seem not to link with the openssl-library. Try to add
[..] -lssl [..]
in addition to your other libraries when linking.
Your gcc-line seems incomplete as well:
gcc -o -lpthread -lm server.c
The -o argument should be followed by a output-filename (in this case it will use "-lpthread" as filename.

Related

exec fails to find files after root changed using pivot_root

I'm trying to experiment with namespaces and chroot emulation, and have succeeded in creating an environment that only has the new root in it (confirmed by a directory traversal), but for some reason, I can't seem to execute anything in it.
Here is a minimally reproducible example:
mkdir /jail
mkdir /jail/bin
mkdir /jail/usr
mkdir /jail/lib
cp /bin/bash /jail/bin
/* isoroot.c */
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sched.h> /* use clone */
#include <syscall.h>
#include <sys/mount.h>
#include <sched.h>
#ifndef pivot_root
#define pivot_root(new, old) syscall(SYS_pivot_root, new, old)
#endif
int main(int argc, char *argv[])
{
int res = 0;
const char *new_root = "/jail";
const char *old_root = "/oldroot";
(void) argc;
if (unshare(CLONE_NEWNS)) { /* Must be executed with privileges. Don't forget this, or we basically blow up the system since we'll remove the real mount */
fprintf(stderr, "unshare: %s\n", strerror(errno));
_exit(errno);
}
if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) { /* Prevent shared propagation */
fprintf(stderr, "mount: %s\n", strerror(errno));
_exit(errno);
}
if (mount(new_root, new_root, NULL, MS_BIND, NULL)) { /* Ensure new_root is a mount point */
fprintf(stderr, "mount: %s\n", strerror(errno));
_exit(errno);
}
if (mkdir("/jail/oldroot", 0777)) { /* should be new_root/old_root */
fprintf(stderr, "mkdir: %s\n", strerror(errno));
_exit(errno);
}
/* Mount some things we need before we dismount the old root */
/* /usr has /bin, /sbin, /lib, and /lib64 */
res = mount("/usr", "/jail/usr", NULL, MS_BIND | MS_REC | MS_RDONLY, NULL);
if (res) {
fprintf(stderr, "mount usr failed: %s\n", strerror(errno));
}
if (pivot_root(new_root, "/jail/oldroot")) { /* Actually make it the new root */
fprintf(stderr, "pivot_root: %s\n", strerror(errno));
_exit(errno);
}
if (chdir("/")) { /* Switch to new root */
fprintf(stderr, "chdir failed: %s\n", strerror(errno));
_exit(errno);
}
if (umount2(old_root, MNT_DETACH)) { /* Unmount old root */
fprintf(stderr, "umount2 failed: %s\n", strerror(errno));
_exit(errno);
}
if (rmdir(old_root)) { /* Remove old mount point */
fprintf(stderr, "rmdir failed: %s\n", strerror(errno));
_exit(errno);
}
if (access("/bin/bash", X_OK)) {
fprintf(stderr, "bash4 not found: %s\n", strerror(errno));
_exit(errno);
}
printf("Got all the way here\n");
execvp("/bin/bash", argv);
fprintf(stderr, "%s\n", strerror(errno));
exit(errno);
}
Compile with:
gcc -Wall -Werror -Wunused -Wextra -Wmaybe-uninitialized -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement -Wmissing-declarations -Wmissing-format-attribute -Wnull-dereference -Wformat=2 -Wshadow -Wsizeof-pointer-memaccess -std=gnu99 -pthread -O0 -g -Wstack-protector -fno-omit-frame-pointer -fwrapv -D_FORTIFY_SOURCE=2 -c isoroot.c
gcc -Wall -Werror -Wunused -Wextra -Wmaybe-uninitialized -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement -Wmissing-declarations -Wmissing-format-attribute -Wnull-dereference -Wformat=2 -Wshadow -Wsizeof-pointer-memaccess -std=gnu99 -pthread -O0 -g -Wstack-protector -fno-omit-frame-pointer -fwrapv -D_FORTIFY_SOURCE=2 -o isoroot *.o
What seems particularly strange is that the last access succeeds, indicating that access can find /bin/bash. However, execvp always fails with No such file or directory.
I'm assuming since that access is using the new namespace at this point, exec would too, but for some reason, that doesn't seem to hold here. Is there some trick to exec being able to find stuff after the root has been changed?
As a comparison, the example here does work in the sense that exec succeeds, but it doesn't really seem to pivot the root in that everything from the real root is still visible: https://lkml.iu.edu/hypermail/linux/kernel/0803.0/1805.html
chdir("/jail");
unshare(CLONE_NEWNS);
mount("/jail", "/jail", NULL, MS_BIND, NULL);
pivot_root("/jail", "/jail/old_root");
chdir("/");
mount("/old_root/bin", "bin", NULL, MS_BIND, NULL);
mount("/old_root/usr", "usr", NULL, MS_BIND, NULL);
mount("/old_root/lib", "lib", NULL, MS_BIND, NULL);
umount2("/old_root", MNT_DETACH);
exec("/busybox");
Using ldd, I've confirmed I should have everything needed to run something like /bin/sh as well. Both /bin and /lib, as well as /lib64 are simply symlinks to folders in
# ldd /bin/bash
linux-vdso.so.1 (0x00007ffc99116000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fd041cb9000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd041cb3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd041ade000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd041e3a000)
I tried manually adding the symlinks too, just in case, but I just get "Error: File already exists" when I do this at the end, just before exec:
if (symlink("/bin", "/usr/bin")) {
fprintf(stderr, "symlink failed: %s\n", strerror(errno));
}
if (symlink("/lib", "/usr/lib")) {
fprintf(stderr, "symlink failed: %s\n", strerror(errno));
}
if (symlink("/lib64", "/usr/lib64")) {
fprintf(stderr, "symlink failed: %s\n", strerror(errno));
}
Trying to mount /proc and /lib64 fail although /bin and /lib succeed (even though all of these except /proc are symlinks to /usr/<dir>

"Undefined symbols for architecture x86_64" compiling sample code for D2XX (using XCODE 4.5, OS X 10.7.5)

I didn't see anything on Stack Overflow for this particular file. I downloaded and installed the drivers for a FTDI serial-usb adapter from http://www.ftdichip.com/Drivers/D2XX.htm for OS X 10.7. Right now, I'm trying to get sample code going from the folder entitled "Simple" inside the included samples. I made a new XCODE (4.5) project and imported the necessary.
I'm getting the following compilation errors:
Ld /Users/availableimac/Library/Developer/Xcode/DerivedData/SerialTest-djxlngfrdsbhhdacorrnmcgxxdpc/Build/Products/Debug/SerialTest normal x86_64
cd /Users/availableimac/Documents/HardwareDev/SerialTest
setenv MACOSX_DEPLOYMENT_TARGET 10.7
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -L/Users/availableimac/Library/Developer/Xcode/DerivedData/SerialTest-djxlngfrdsbhhdacorrnmcgxxdpc/Build/Products/Debug -F/Users/availableimac/Library/Developer/Xcode/DerivedData/SerialTest-djxlngfrdsbhhdacorrnmcgxxdpc/Build/Products/Debug -filelist /Users/availableimac/Library/Developer/Xcode/DerivedData/SerialTest-djxlngfrdsbhhdacorrnmcgxxdpc/Build/Intermediates/SerialTest.build/Debug/SerialTest.build/Objects-normal/x86_64/SerialTest.LinkFileList -mmacosx-version-min=10.7 -o /Users/availableimac/Library/Developer/Xcode/DerivedData/SerialTest-djxlngfrdsbhhdacorrnmcgxxdpc/Build/Products/Debug/SerialTest
Undefined symbols for architecture x86_64:
"_FT_Close", referenced from:
_main in main.o
"_FT_GetQueueStatus", referenced from:
_main in main.o
"_FT_ListDevices", referenced from:
_main in main.o
"_FT_OpenEx", referenced from:
_main in main.o
"_FT_Read", referenced from:
_main in main.o
"_FT_SetBaudRate", referenced from:
_main in main.o
"_FT_Write", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You can get the project folder here: https://drive.google.com/file/d/0B602Cy_Ktj0BdUVxZ3JrUVdpZlU/view?usp=sharing
The makefile isn't part of the xCode project. It was part of the original sample code. I don't have a clue how to fix this. I'd appreciate any kind of help!
main.c:
/*
Simple example to open a maximum of 4 devices - write some data then read it back.
Shows one method of using list devices also.
Assumes the devices have a loopback connector on them and they also have a serial number
To build use the following gcc statement
(assuming you have the d2xx library in the /usr/local/lib directory).
gcc -o simple main.c -L. -lftd2xx -Wl,-rpath /usr/local/lib
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "ftd2xx.h"
#define BUF_SIZE 0x10
#define MAX_DEVICES 5
int iDevicesOpen;
static void dumpBuffer(unsigned char *buffer, int elements)
{
int j;
printf(" [");
for (j = 0; j < elements; j++)
{
if (j > 0)
printf(", ");
printf("0x%02X", (unsigned int)buffer[j]);
}
printf("]\n");
}
int main()
{
unsigned char cBufWrite[BUF_SIZE];
unsigned char * pcBufRead = NULL;
char * pcBufLD[MAX_DEVICES + 1];
char cBufLD[MAX_DEVICES][64];
DWORD dwRxSize = 0;
DWORD dwBytesWritten, dwBytesRead;
FT_STATUS ftStatus;
FT_HANDLE ftHandle[MAX_DEVICES];
int iNumDevs = 0;
int i, j;
for(i = 0; i < MAX_DEVICES; i++) {
pcBufLD[i] = cBufLD[i];
}
pcBufLD[MAX_DEVICES] = NULL;
ftStatus = FT_ListDevices(pcBufLD, &iNumDevs, FT_LIST_ALL | FT_OPEN_BY_SERIAL_NUMBER);
if(ftStatus != FT_OK) {
printf("Error: FT_ListDevices(%d)\n", (int)ftStatus);
return 1;
}
for(i = 0; ( (i <MAX_DEVICES) && (i < iNumDevs) ); i++) {
printf("Device %d Serial Number - %s\n", i, cBufLD[i]);
}
for(j = 0; j < BUF_SIZE; j++) {
cBufWrite[j] = j;
}
for(i = 0; ( (i <MAX_DEVICES) && (i < iNumDevs) ) ; i++) {
/* Setup */
if((ftStatus = FT_OpenEx(cBufLD[i], FT_OPEN_BY_SERIAL_NUMBER, &ftHandle[i])) != FT_OK){
/*
This can fail if the ftdi_sio driver is loaded
use lsmod to check this and rmmod ftdi_sio to remove
also rmmod usbserial
*/
printf("Error FT_OpenEx(%d), device %d\n", (int)ftStatus, i);
printf("Use lsmod to check if ftdi_sio (and usbserial) are present.\n");
printf("If so, unload them using rmmod, as they conflict with ftd2xx.\n");
return 1;
}
printf("Opened device %s\n", cBufLD[i]);
iDevicesOpen++;
if((ftStatus = FT_SetBaudRate(ftHandle[i], 9600)) != FT_OK) {
printf("Error FT_SetBaudRate(%d), cBufLD[i] = %s\n", (int)ftStatus, cBufLD[i]);
break;
}
printf("Calling FT_Write with this write-buffer:\n");
dumpBuffer(cBufWrite, BUF_SIZE);
/* Write */
ftStatus = FT_Write(ftHandle[i], cBufWrite, BUF_SIZE, &dwBytesWritten);
if (ftStatus != FT_OK) {
printf("Error FT_Write(%d)\n", (int)ftStatus);
break;
}
if (dwBytesWritten != (DWORD)BUF_SIZE) {
printf("FT_Write only wrote %d (of %d) bytes\n",
(int)dwBytesWritten,
BUF_SIZE);
break;
}
sleep(1);
/* Read */
dwRxSize = 0;
while ((dwRxSize < BUF_SIZE) && (ftStatus == FT_OK)) {
ftStatus = FT_GetQueueStatus(ftHandle[i], &dwRxSize);
}
if(ftStatus == FT_OK) {
pcBufRead = realloc(pcBufRead, dwRxSize);
memset(pcBufRead, 0xFF, dwRxSize);
printf("Calling FT_Read with this read-buffer:\n");
dumpBuffer(pcBufRead, dwRxSize);
ftStatus = FT_Read(ftHandle[i], pcBufRead, dwRxSize, &dwBytesRead);
if (ftStatus != FT_OK) {
printf("Error FT_Read(%d)\n", (int)ftStatus);
break;
}
if (dwBytesRead != dwRxSize) {
printf("FT_Read only read %d (of %d) bytes\n",
(int)dwBytesRead,
(int)dwRxSize);
break;
}
printf("FT_Read read %d bytes. Read-buffer is now:\n",
(int)dwBytesRead);
dumpBuffer(pcBufRead, (int)dwBytesRead);
if (0 != memcmp(cBufWrite, pcBufRead, BUF_SIZE)) {
printf("Error: read-buffer does not match write-buffer.\n");
break;
}
printf("%s test passed.\n", cBufLD[i]);
}
else {
printf("Error FT_GetQueueStatus(%d)\n", (int)ftStatus);
}
}
iDevicesOpen = i;
/* Cleanup */
for(i = 0; i < iDevicesOpen; i++) {
FT_Close(ftHandle[i]);
printf("Closed device %s\n", cBufLD[i]);
}
if(pcBufRead)
free(pcBufRead);
return 0;
}

ppu-ld cannot find -lspe

I am trying to compile the code below, on CELL BE Simulator(mambo).
//hello.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <libspe.h>
#include <sched.h>
extern spe_program_handle_t hello_spu;
spe_gid_t gid;
speid_t speids[8];
int status[8];
int main(int argc, char *argv[]){
int i;
printf("Hello World!\n");
gid = spe_create_group (SCHED_OTHER, 0, 1);
if (gid == NULL) {
fprintf(stderr, "Failed spe_create_group(errno=%d)\n", errno);
return -1;
}
if (spe_group_max (gid) < 8) {
fprintf(stderr, "System doesn't have eight working SPEs. I'm leaving.\n");
return -1;
}
for (i = 0; i < 8; i++) {
speids[i] = spe_create_thread (gid, &hello_spu,NULL, NULL, -1, 0);
if (speids[i] == NULL) {
fprintf (stderr, "FAILED: spe_create_thread(num=%d, errno=%d)\n",i, errno);
exit (3+i);
}
}
for (i=0; i<8; ++i){
spe_wait(speids[i], &status[i], 0);
}
__asm__ __volatile__ ("sync" : : : "memory");
return 0;
}
//Makefile
########################################################################
# Target
########################################################################
PROGRAM_ppu64 = hello
########################################################################
# Local Defines
########################################################################
IMPORTS = ../spu/hello_spu.a -lspe
########################################################################
# make.footer
########################################################################
include /opt/cell/sdk/buildutils/make.footer
After compiling the this, it provides with the following output.
$make
/opt/cell/toolchain/bin/ppu-gcc -W -Wall -Winline -I. -I /opt/cell/sysroot usr/include -I /opt/cell/sysroot/opt/cell/sdk/usr/include -mabi=altivec -maltivec -O3 -c
hello.c
hello.c: In function 'main':
hello.c:12: warning: unused parameter 'argc'
hello.c:12: warning: unused parameter 'argv'
/opt/cell/toolchain/bin/ppu-gcc -o hello hello.o -L/opt/cell/sysroot/usr/lib64 -L/opt/cell/sysroot/opt/cell/sdk/usr/lib64 -R/opt/cell/sdk/usr/lib64 ../spu/hello_spu.a -lspe
/opt/cell/toolchain/bin/ppu-ld: cannot find -lspe
collect2: ld returned 1 exit status
make: *** [hello] Error 1
'ld' cannot find the -lspe library.The "/opt/cell/sysroot/usr/lib" directory contains following libraries and files,
alf, libblas.so, libc_stubs.a, libieee.a, libnetpbm.so.10, libnuma.so.1, libsimdmath.so.3,
crt1.o, libblas.so.1, libdl.a, libm.a, libnetpbm.so.10.35, libpthread.a, libsimdmath.so.3.0.3,
crti.o, libBrokenLocale.a, libdl.so, libmass.a, libnldbl_nonshared.a, libpthread_nonshared.a, libspe2.so,
crtn.o, libBrokenLocale.so, libg.a, libmassv.a, libnsl.a, libpthread.so, libspe2.so.2,
gconv, libbsd.a, libgmp.a, libmcheck.a, libnsl.so, libresolv.a, libspe2.so.2.2.0,
gcrt1.o, libbsd-compat.a, libgmp.so, libmp.a, libnss_compat.so, libresolv.so, libthread_db.so,
libalf.a, libc.a, libgmp.so.3, libmpfr.a, libnss_dns.so, librpcsvc.a, libutil.a,
libalf.so, libcidn.so, libgmp.so.3.3.3, libmp.so, libnss_files.so, librt.a, libutil.so,
libalf.so.3, libc_nonshared.a, libgmpxx.a, libmp.so.3, libnss_hesiod.so, librtkaio.a, Mcrt1.o,
libalf.so.3.0.0, libcrypt.a, libgmpxx.so, libmp.so.3.1.7, libnss_nisplus.so, librt.so, Scrt1.o,
libanl.a, libcrypt.so, libgmpxx.so.3, libm.so, libnss_nis.so, libsimdmath.a,
libanl.so, libc.so, libgmpxx.so.3.0.5, libnetpbm.so, libnuma.so, libsimdmath.so
How do I link libspe2.so to libspe.so?
Please, help.
You don't link those together. They are different things. You either update your makefile to use -lspe2 if that's the version of the library you want or you install the version of the library that installs the libspe.so library.

Compilation fails with "error: ‘next_ioctl’ undeclared (first use in this function)" despite I included dlfcn.h

Trying to compile an example of wrapping library from here
I had to include stdio.h and stdlib.h, and came to that code:
#define _GNU_SOURCE
#define _USE_GNU
#include <signal.h>
#include <execinfo.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
static void show_stackframe() {
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;
trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
printf("[bt] Execution path:\n");
for (i=0; i < trace_size; ++i)
printf("[bt] %s\n", messages[i]);
}
int ioctl(int fd, int request, void *data)
{
char *msg;
if (next_ioctl == NULL) {
fprintf(stderr, "ioctl : wrapping ioctl\n");
fflush(stderr);
// next_ioctl = dlsym((void *) -11, /* RTLD_NEXT, */ "ioctl");
next_ioctl = dlsym(RTLD_NEXT, "ioctl");
fprintf(stderr, "next_ioctl = %p\n", next_ioctl);
fflush(stderr);
if ((msg = dlerror()) != NULL) {
fprintf(stderr, "ioctl: dlopen failed : %s\n", msg);
fflush(stderr);
exit(1);
} else
fprintf(stderr, "ioctl: wrapping done\n");
fflush(stderr);
}
if (request == 1) { /* SCSI_IOCTL_SEND_COMMAND ? */
/* call back trace */
fprintf(stderr, "SCSI_IOCTL_SEND_COMMAND ioctl\n");
fflush(stderr);
show_stackframe();
}
return next_ioctl(fd, request, data);
}
and Makefile
#
# Makefile
#
all: libs test_ioctl
libs: libwrap_ioctl.so
libwrap_ioctl.so: wrap_ioctl.c
rm -f libwrap_ioctl.so*
gcc -fPIC -shared -Wl,-soname,libwrap_ioctl.so.1 -ldl -o libwrap_ioctl.so.1.0 wrap_ioctl.c
ln -s libwrap_ioctl.so.1.0 libwrap_ioctl.so.1
ln -s libwrap_ioctl.so.1 libwrap_ioctl.so
clean:
rm -f libwrap_ioctl.so* test_ioctl
and stuck in these errors, despite dlfcn.h is included.
~/my_src/native/glibc_wrapper > make
rm -f libwrap_ioctl.so*
gcc -fPIC -shared -Wl,-soname,libwrap_ioctl.so.1 -ldl -o libwrap_ioctl.so.1.0 wrap_ioctl.c
wrap_ioctl.c: In function ‘ioctl’:
wrap_ioctl.c:26: error: ‘next_ioctl’ undeclared (first use in this function)
wrap_ioctl.c:26: error: (Each undeclared identifier is reported only once
wrap_ioctl.c:26: error: for each function it appears in.)
make: *** [libwrap_ioctl.so] Ошибка 1
dlfcn.h itself doesn't define any symbol with name next_smth. (In SUS, dlfcn.h only defines several dl* functions and RTLD_ macro: http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html)
You should define this as pointer to function in your program code in explicit way. Something like this: (taken from https://port70.net/svn/misc/remac/remac.c or from https://github.com/itm/forward-sensor/blob/master/preload.c or ... any google search for "next_ioctl"):
static int (*next_ioctl) (int fd, int request, void *data) = NULL;
Or, if you want a collective blog-reading session, there is additional line in the blog post with ioctl overloading: http://scaryreasoner.wordpress.com/2007/11/17/using-ld_preload-libraries-and-glibc-backtrace-function-for-debugging/ (just before first huge code fragment)
Then, declare a function pointer to hold the value
of the “real” ioctl() function from glibc:
static int (*next_ioctl)(int fd, int request, void *data) = NULL;
Then declare your replacement ioctl function:
You missed to declare next_ioctl.
Just add
void * next_ioctl = NULL;
int (*next_ioctl) (int, int, ...) = NULL;
to main().

pthread_create failed and returned -1 (or 4294967295)

I'm trying to reproduce an example from Network Security with OpenSSL (by Chandra et al). The program consists of client.c server.c common.h and common.c. client.c simply creates a connection to the server on port 6012 and reads data from stdin and then send those data to the server. The server.c reads data from socket and writes it back out to stdout.
The problem is that server.c always get stuck in if(BIO_do_accept(acc) <= 0) at line 62 and never gets data sent from client.c, which runs perfectly fine. I later found the problem is that pthread_create(...) at line 66 ( which is defined as THREAD_CREATE(...) in common.h) failed and it returned 4294967295. Because THREAD_CREATE(...) failed, the program never get a chance to run do_server_loop in server_thread(...), which explains why the server never got the data from client.
How should I interpret the return values from pthread_create and how should I fix it?
PS. I later used strerror to convert 4294967295 and it returned "Unknown error".
Any help will be much appreciated!
//////////////////////////////////////////////////
Here is server.c:
#include "common.h"
void do_server_loop(BIO *conn)
{
int err, nread;
char buf[80];
do
{
fprintf(stderr, "server_loop executed.\n");
for(nread = 0; nread < sizeof(buf); nread += err)
{
err = BIO_read(conn, buf + nread, sizeof(buf) - nread);
if(err <= 0){
break;
}
}
fwrite(buf, 1, nread, stdout);
}
while (err > 0);
}
void THREAD_CC server_thread(void *arg)
{
fprintf(stderr, "server_thread(void *arg) executed.\n");
BIO *client = (BIO *)arg;
#ifndef WIN32
pthread_detach(pthread_self());
#endif
fprintf(stderr, "Connection opened.\n");
do_server_loop(client);
fprintf(stderr, "Connection closed.\n");
BIO_free(client);
ERR_remove_state(0);
#ifdef WIN32
_endthread();
#else
return 0;
#endif
}
int main(int argc, char *argv[])
{
BIO *acc, *client;
int thread_create_result;
THREAD_TYPE tid;
init_OpenSSL();
acc = BIO_new_accept(PORT);
if(!acc){
int_error("Error creating server socket");
}
if(BIO_do_accept(acc) <= 0){
int_error("Error binding server socket");
}
for(;;)
{
if(BIO_do_accept(acc) <= 0){
int_error("Error accepting connection");
}
client = BIO_pop(acc);
thread_create_result = THREAD_CREATE(tid, server_thread, client);
if(thread_create_result != 0){
fprintf(stderr, "THREAD_CREATE failed! returns: %s.\n", \
strerror(thread_create_result));
fprintf(stderr, "thread_create_result has the value: %u.\n", \
thread_create_result);
exit(-1);
}
}
BIO_free(acc);
return 0;
}
Here is common.h
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/objects.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#ifndef WIN32
#include <pthread.h>
#define THREAD_CC *
#define THREAD_TYPE pthread_t
#define THREAD_CREATE(tid, entry, arg) pthread_create(&(tid), NULL, \
(entry), (arg))
#else
#include <windows.h>
#include <process.h>
#define THREAD_CC __cdecl
#define THREAD_TYPE DWORD
#define THREAD_CREATE(tid, entry, arg) do { _beginthread((entry), 0, (arg));\
(tid) = GetCurrentThreadId();\
} while (0)
#endif
#define PORT "6012" //port
#define SERVER "10.1.251.24" //server address
#define CLIENT "10.1.21.46" //client address
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
void handle_error(const char *file, int lineno, const char *msg);
void init_OpenSSL(void);
Makefile:
CC = gcc
OPENSSLDIR = /usr/local/ssl
#CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2 -D_REENTRANT -D__EXTENSIONS__
CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2
RPATH = -R${OPENSSLDIR}/lib
#LD = ${RPATH} -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -lpthread
LD = -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -pthread
OBJS = common.o
PROGS = server
all: ${PROGS}
server: server.o ${OBJS}
${CC} server.o ${OBJS} -o server ${LD}
clean:;
${RM} ${PROGS} *.ln *.BAK *.bak *.o
Change
if(thread_create_result = !0){
to
if(thread_create_result != 0){
Besides, you can use strerror function to convert error code to human-readable form.
add -D_REENTRANT on compile command lines and -lpthread on the link command line.
-D_REENTRANT will tell C/C++ libraries that your program is in multithread mode and -lpthread just load the shared library libpthread.so at runtime. I found this at William Garrison's POSIX threads tutorial and this link.
Here is the Makefile:
CC = gcc
OPENSSLDIR = /usr/local/ssl
CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2 -D_REENTRANT -D__EXTENSIONS__
RPATH = -R${OPENSSLDIR}/lib
LD = ${RPATH} -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -lpthread
OBJS = common.o
PROGS = server
all: ${PROGS}
server: server.o ${OBJS}
${CC} server.o ${OBJS} -o server ${LD}
clean:;
${RM} ${PROGS} *.ln *.BAK *.bak *.o

Resources