TCP Server - new process for each client? - c

Warning: I'm quite new to C and memory mgmt and all that stuff (coming from interpreted/JITed languages).
So I'm making a little library for creating TCP servers easily (as an exercise in network programming). An example of usage could look like the following:
#include <stdio.h>
#include "ohsimpletcp.h"
void echo(int socket_fd) {
char *message = malloc(100 * sizeof(char));
while (ost_receive(socket_fd, message, 100) > 0) {
ost_send(socket_fd, message);
}
}
int main() {
if (ost_serve(1337, echo) == -1) {
perror("An error occurred");
return 1;
}
return 0;
}
But my question is, for making this thing smoothly concurrent for a high number of clients, do I need to create a new process for every connected client in the backend? Or could I solve this with select() somehow?
ohsimpletcp.h:
#ifndef REG4IN_OST_H
#define REG4IN_OST_H 1
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int ost_serve(int port, void (*handler)(int socket_fd));
int ost_send(int socket_fd, char *message);
int ost_receive(int socket_fd, char *message, int length);
#endif

Related

Unable to send UDP get request to memcached server with libmemcached module

I'm writing a Memcached UDP client with libmemcached/memcached.h to send some arbitrary loads on Memcached server. I can send set requests in UDP but I'm unable to send get requests, here is the snippet I wrote for this!
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libmemcached/memcached.h>
#include <time.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
int main(int argc, char *argv[])
{
memcached_server_st *servers = NULL;
memcached_st *memc;
memcached_return rc;
char * res;
char *key= "kay";
int size = 1000;
char * value = malloc(size);
uint32_t flags;
size_t return_value_length;
char * ip = argv[2];
memset(value, 1, size);
memc = memcached_create(NULL);
servers= memcached_server_list_append(servers, ip, 11211, &rc);
rc = memcached_server_push(memc, servers);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, (uint64_t)1);
rc = memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0);
if (rc == MEMCACHED_SUCCESS)
fprintf(stderr,"Key stored successfully\n");
else
fprintf(stderr,"Couldn't store key: %s\n",memcached_strerror(memc, rc));
while ( true)
{
res = memcached_get(memc, key, strlen(key), &return_value_length, &flags, &rc);
free(res);
if(rc != MEMCACHED_SUCCESS)
{
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
}
}
memcached_free(memc);
return 0;
Actually, get requests always are unsuccessful!!! I also monitored the packets with Wireshark the client doesn't even send any packet out to the server!!! And it just got failed while sending get request.
Is there any obvious problem in the code which I couldn't see?
Thank you
According to the manpage of memcached_behaviour_set():
The following operations will return MEMCACHED_NOT_SUPPORTED when
executed with the MEMCACHED_BEHAVIOR_USE_UDP enabled:
memcached_version(), memcached_stat(), memcached_get(),
memcached_get_by_key(), memcached_mget(), memcached_mget_by_key(),
memcached_fetch(), memcached_fetch_result(),
memcached_fetch_execute().
So indeed, memcached_get() does not work when the memcached-handle is set to UDP transport. You will have to use TCP for that.

Initializing a struct results in Segmentation Fault

I have a simple struct as follows:
typedef struct {
char *raw_headers;
char headers[128][512][512];
} HTTPrequest;
Now in the same file I have a function as follows:
void init_request(char *raw_headers) {
HTTPrequest request;
request.raw_headers = raw_headers;
}
This results in a Segmentation Fault when running the output binary.
I compile the file, as
$ gcc Server.c -o Builds/debug
And, I run the executable as,
$ ./Builds/debug
This is my original file as requested:
Parser.h
typedef struct {
char *raw_headers;
char headers[128][512][512];
} HTTPrequest;
void parser_init(char *raw_headers) {
char *token, *key_value = NULL;
token = strtok(raw_headers, "\r\n");
int line_counter = 1
HTTPrequest request;
request.raw_headers = raw_headers;
while (token) {
char *line = token;
if(line_counter != 1) {
}
token = strtok(NULL, "\r\n");
line_counter++;
}
}
Server.h
int socket_create() {
return socket(AF_INET, SOCK_STREAM, 0);
}
void infinite_loop(int socketFD) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
printf("Starting infinite loop, don't worry, everything would be okay!\n");
do {
int connectionFD = accept(socketFD, (struct sockaddr*) NULL, NULL);
/*Accept is a blocking call! The following code wont execute until, accept() returns.*/
strcpy(buffer, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello!");
write(connectionFD, buffer, sizeof(buffer));
char request[2048];
memset(&request, 0, sizeof(request));
read(connectionFD, &request, sizeof(request));
printf("Request received!\n");
// Init the parser.
parser_init(request);
close(connectionFD);
} while (true);
}
Server.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <stdbool.h>
#include "Parser.h"
#include "Server.h"
void main() {
struct sockaddr_in listeningAddr;
int socketFD = socket_create();
memset(&listeningAddr, 0, sizeof(listeningAddr));
listeningAddr.sin_family = AF_INET;
listeningAddr.sin_addr.s_addr = htonl(INADDR_ANY);
listeningAddr.sin_port = htons(8070);
bind(socketFD, (struct sockaddr*) &listeningAddr, sizeof(listeningAddr));
if(listen(socketFD, 5) == -1) {
printf("Woah there! I couldn't startup the server!");
}
infinite_loop(socketFD);
}
Also, the error message: Segmentation fault (core dumped)
The headers member (32MiB) makes your struct too big to fit on most default system-provided stacks (8MiB on Linux).
Make it smaller, and trivial MCVEs such as:
typedef struct {
char *raw_headers;
char headers/*[128]*/[512][512]; }
HTTPrequest;
void init_request(char *raw_headers) {
HTTPrequest request;
request.raw_headers = raw_headers;
}
int main()
{
init_request("hello, world");
}
will work, although, initializing an on-stack struct only to have it discarded by the function return is not very meaningful
(Initializer functions will usually take a pointer to the struct they're initializing and initialize the object through that pointer.)
Although your HTTPrequest is simple, it is over 32MB in size. You most probably encounter a stack overflow...
That's a typical case of Stack overflow!
The reason is that your struct HTTPrequest is too big, more than 32 MB. The 3D array has a size of 128 * 512 * 512 = 33554432 bytes, since it's of type char.
In any case, 3D arrays are barely used, and only in special cases. Reconsider your design and try to make that array a 2D instead of a 3D.

Connection refused on wpa_ctrl_open

I am trying to use C code to access wpa_supplicant in an ARM embedded system running linux. After searching, I realise that I could use wpa_supplicant control interface. I try to open a connection using wpa_ctrl_open(), and resulted in "Connection refused" error:
Failed to connect to wpa_supplicant global interface: /var/run/wpa_supplicant error: Connection refused
The code I am using to test:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <netinet/if_ether.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "includes.h"
#ifdef CONFIG_CTRL_IFACE_UNIX
#include <dirent.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
#include "wpa_ctrl.h"
#include "common.h"
struct wpa_ctrl {
int s;
#ifdef CONFIG_CTRL_IFACE_UDP
struct sockaddr_in local;
struct sockaddr_in dest;
#else // CONFIG_CTRL_IFACE_UDP
struct sockaddr_un local;
struct sockaddr_un dest;
#endif // CONFIG_CTRL_IFACE_UDP
};
static struct wpa_ctrl *ctrl_conn;
int main(int argc,char **argv)
{
const char *global = "/var/run/wpa_supplicant";
ctrl_conn = wpa_ctrl_open(global);
if (ctrl_conn == NULL)
{
fprintf(stderr, "Failed to connect to wpa_supplicant "
"global interface: %s error: %s\n",global,strerror(errno));
return -1;
}
else
{
printf("Success\n");
}
return 0;
}
After tracing the code in wpa_ctrl.c, I found the problem is on the following IF condition, inside wpa_ctrl_open2() function:
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,sizeof(ctrl->dest)) < 0)
I do not know what is the problem and how I can solve it.
On the same machine, I tried to run wpa_cli and it can access wpa_supplicant perfectly.
I used the following command to compile:
gcc -o test_wpa main.c wpa_ctrl.c os_unix.c -DCONFIG_BACKEND_FILE -DCONFIG_IEEE80211W -DCONFIG_DRIVER_WEXT -DCONFIG_WIRELESS_EXTENSION -DCONFIG_DRIVER_NL80211 -DCONFIG_LIBNL20 -DEAP_PSK -DIEEE8021X_EAPOL -DCONFIG_SHA256 -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX -DCONFIG_SME -lrt
wpa_supplicant code (including wpa_ctrl.c & os_unix.c) can be download at here:
http://w1.fi/releases/wpa_supplicant-2.5.tar.gz
Many thanks in advance!
I found the way to solve the problem, add "wlan0" after the path:
const char *global = "/var/run/wpa_supplicant/wlan0";
ctrl_conn = wpa_ctrl_open(global);

How to "bypass" pthreads limit number

I have a little problem here. I know Linux limits the number of threads of an user can actually run.
I'm using pthread_create and an array of pthread_t limited with 50 ( pthread_t tid[50]; ). I have a for cycle that each time that limit reaches 50 every thread on pthread_t array is killed.
How? I tested almost everything. with pthread_kill(tid[w],SIGKILL); w is a simple cycle control variable goes from 0 to 50. I already tested pthread_cancel(tid[w]); and the problem keeps.
So what is the problem?
Everytime I reach 380 thread number I can't create more. But I'm killing with cancel or kill. So what is happening?
The objective of the program is a network scanner. To be faster I need like 500 threads with like 2 seconds of timeout to test IP's and ports.
Anyone knows how to "go arround" this problem?
I thought that I could kill the thread it would solve the problem but I was wrong :(
Without use ulimit or in /proc/sys/kernel/threads_max changing values, I looked at pthread_attr_setstacksize but I'm a bit confused :P
any ideas?
EDIT
The code as requested :P
I'm going to put ALL code here:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#ifndef SOL_TCP
#define SOL_TCP 6
#endif
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT 18 //retry
#endif
#define MAX_TH 250
struct ar_stc{
char* ip;
int port;
};
char* ret[2];
int porar[2];
pthread_t tid[MAX_TH];
void create_port_scan_th(char* host,int p,int j);
//cares about args.
//this is not helpful for the threads post on stackoverflow. skip this function
char** arguments_handle(int argc,char **arg)
{
char p[]="-p";
char h[]="-h";
size_t _p,_h;
_p=(size_t)strlen(p);
_h=(size_t)strlen(h);
if(argc!=5)
{
printf("Usage:./file -p PORT-RANGE -h HOST.IP\n");
exit(1);
}
if(strncmp(arg[1],p,_p)==0 || strncmp(arg[1],h,_h)==0 && strncmp(arg[3],p,_p)==0 || strncmp(arg[3],h,_h)==0)
{
if(strncmp(arg[1],p,_p)==0)
{
strncpy(ret[0],arg[2],strlen(arg[2]));
}
else
{
strncpy(ret[1],arg[2],strlen(arg[2]));
}
if(strncmp(arg[3],h,_h)==0)
{
strncpy(ret[1],arg[4],strlen(arg[4]));
}
else
{
strncpy(ret[0],arg[4],strlen(arg[4]));
}
}
return ret;
}
int* take_ports(char *arg)
{
char* ports[2];
ports[0] = malloc(5);
ports[1] = malloc(5);
memset(ports[0],0,5);
memset(ports[1],0,5);
char tmp[5];
int len = strlen(arg);
int i,j=0,x=0;
char min_p[5],max_p[5];
for(i=0;i<len;i++)
{
if(arg[i]=='-')
{
min_p[x]='\0';
j=1;
x=0;
continue;
}
else
{
if(j==0)
min_p[x]=arg[i];
else
max_p[x]=arg[i];
}
x++;
}
max_p[x]='\0';
porar[1]=atoi(max_p);
porar[0]=atoi(min_p);
free(ports[0]);
free(ports[1]);
return porar;
}
void *check_port(void* ar_p)
{
struct ar_stc *ar =ar_p;
char* ip = ar->ip;
int port = ar->port;
int s,conexao;
int timeout = 1000; //1 second timeout
s=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in dst;
setsockopt(s,SOL_TCP,TCP_USER_TIMEOUT,(char*)&timeout,sizeof(timeout)); //NOT WORKING :(
if(s<0)
{
printf("\nCouldnt create socket\nPremissions maybe?\n");
exit(1);
}
dst.sin_family = AF_INET;
dst.sin_port = htons(port);
dst.sin_addr.s_addr = inet_addr(ip);
bzero(&(dst.sin_zero),8);
//printf("\nChecking: %d...",port);
conexao = connect(s,(struct sockaddr*)&dst,sizeof(dst));
if(conexao <0)
{
printf("TCP/%d:CLOSED!\n",port); //just to make sure the thread is running
close(s);
return;
}
else
{
printf("TCP/%d:OPEN!\n",port);
close(s);
return;
}
}
int main(int argc, char **argv)
{
int open_ports[65535];
int open_ports_count=0;
int min_p,max_p;
int* p;
ret[0] = malloc(20);
ret[1] = malloc(20);
memset(ret[0],0,20);
memset(ret[1],0,20);
char** ipnport;
ipnport = arguments_handle(argc,argv);
printf("The IP is :%s and the range is %s\n",ipnport[1],ipnport[0]);
p=take_ports(ipnport[0]);
min_p=p[0];
max_p=p[1];
printf("Min port:%d e max port:%d\n",min_p,max_p);
int i;
int thread_count=-1;
for(i=min_p;i<=max_p;i++)
{
thread_count++;
create_port_scan_th(ipnport[1],i,thread_count);
if(thread_count>=MAX_TH)
{
sleep(1);
thread_count=0;
int w;
for(w=0;w<=MAX_TH;w++)
{
pthread_kill(tid[w],SIGKILL);
}
}
}
free(ret[0]);
free(ret[1]);
return 0x0;
}
void create_port_scan_th(char* host,int p,int j)
{
int error;
struct ar_stc *ar;
ar = malloc(sizeof(*ar));
ar->ip=host;
ar->port=p;
error = pthread_create(&(tid[j]),NULL,&check_port,(void*)ar);
if(error!=0)
printf("\nError creating thread:%s\n",strerror(error));
}
But I'm killing with cancel or kill.
First of all, pthread_kill does not kill or end a thread.
(see more at pthread_kill doesnt kill thread C linux or When to use pthread_cancel and not pthread_kill).
If you send SIGKILL to a thread, the entire process will end.
To end a thread, you need to
Make the thread end.
by returning from the thread function, or
calling pthread_exit or
pthread_cancel the thread
Dispose the resources tied to the thread by:
Call pthread_join() on the thread or
make the thread a detached thread.
If you opt for the last point by making the thread detached - which will automatically release the thread when it ends , you can call pthread_detach(pthread_Self()) at the start of your thread function.
Or supply a pthread_attr_t when you call pthread_create(), where you set the thread to a detached state.
As for the total number of threads you can use, linux have a limit on the total number of threads/processes any user can have running.
You can view this with the command ulimit -u

connect Error: "No route to host"

i'm writing a server/client c program based on AX.25 protocol.
The server creating the socket, binding Successfully and listening for coming connections.
the client running in a different thread but fails on connect with " No route to host"
Server code
#include <sys/socket.h>
#include <netax25/ax25.h>
#include <netax25/axlib.h>
#include <netax25/axconfig.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <sys/types.h>
#include <linux/socket.h>
#include <stdlib.h>
#include <sys/un.h>
#include <string.h>
#include <errno.h>
int main(int argc,char **argv,char **envp) {
int ax25_socket = -1;
unsigned char buffer[512];
struct full_sockaddr_ax25 addr, axconnect ;
char *port ="3";// sm0 port number:3
char *call = "OH2BNS-8";// sm0 callsign
bzero((char *) &addr, sizeof(struct full_sockaddr_ax25));
addr.fsa_ax25.sax25_family = AF_AX25;
addr.fsa_ax25.sax25_ndigis = 1;
if (ax25_config_load_ports() == 0) {
printf( "Problem with axports file");
//return -1;
}
char* ax25port = (char*) ax25_config_get_addr(port);
ax25_aton_entry( call, addr.fsa_ax25.sax25_call.ax25_call);
ax25_aton_entry( ax25port, addr.fsa_digipeater[0].ax25_call);
ax25_socket = socket(AF_AX25, SOCK_SEQPACKET, 0);
if (ax25_socket < -1)
printf( "error in create socket");
if (bind(ax25_socket, (struct sockaddr *)&addr, sizeof(struct full_sockaddr_ax25)) < 0) {
perror("bind--");
return -1;
}
if(listen(ax25_socket,2) != 0)
{
printf("cannot listen on socket!\n");
close(ax25_socket);
return 0;
}
puts("listening");
//bzero((char *) &axconnect, sizeof(struct full_sockaddr_ax25));
int len =sizeof(struct full_sockaddr_ax25);
int temp_sock_desc = accept(ax25_socket, (struct sockaddr*)&axconnect, &len);
if (temp_sock_desc == -1)
{
printf("cannot accept client!\n");
close(ax25_socket);
return 0;
}
return 0;
}
Client code
#include <sys/socket.h>
#include <netax25/ax25.h>
#include <netax25/axlib.h>
#include <netax25/axconfig.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <sys/types.h>
#include <linux/socket.h>
#include <stdlib.h>
#include <sys/un.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int ax25_socket = -1;
unsigned char buffer[512];
struct full_sockaddr_ax25 axconnect ;
char *port ="3";// sm0 port number:3
char *call ="OH2BNS-8";// sm0 callsign
bzero((char *) &axconnect, sizeof(struct full_sockaddr_ax25));
axconnect.fsa_ax25.sax25_family = AF_AX25;
axconnect.fsa_ax25.sax25_ndigis = 1;
if (ax25_config_load_ports() == 0) {
printf( "Problem with axports file");
//return -1;
}
char* ax25port = (char*) ax25_config_get_addr(port);
ax25_aton_entry( call, axconnect.fsa_ax25.sax25_call.ax25_call);
ax25_aton_entry( ax25port, axconnect.fsa_digipeater[0].ax25_call);
ax25_socket = socket(AF_AX25, SOCK_SEQPACKET, 0);
if (ax25_socket < -1)
printf( "error in create socket");
if (connect(ax25_socket, (struct sockaddr *)&axconnect, sizeof(struct full_sockaddr_ax25)) != 0) {
perror("--");
switch (errno) {
case ECONNREFUSED:
printf("*** Connection refused\r");
break;
case ENETUNREACH:
printf("*** No known route\r");
break;
case EINTR:
printf("*** Connection timed out\r");
break;
default:
printf("ERROR: cannot connect to AX.25 callsign\r");
break;
}
close(ax25_socket);
}
printf("Connected!!\r");
int n = write(ax25_socket,"Message!!!!",18);
if(n = -1)
{
perror("write--");
}
return 0;
}
Simply put, a " No route to host"" would mean that there is no route for the server IP address in the client's routing table. Are you able to ping the server's IP address? Most likely you should not be able to and ping should say that the server is not reachable. If so, then this error has nothing to do with your program, you are probably running into a connectivity issue.
Can you find the entry for your server in the output of "route -n". If there is none, then you should check for a bigger prefix for the subnet of the server. If that also is not present, then you should confirm that you have a default route setup.
To further confirm, I would do the following two tests. First, what happens if you try to run the client/server on the same box? Second, what happens if you try to run the client/server on two boxes (present in the same subnet) and on the same LAN? If you do not see this issue and your application works just fine, then this should confirm that you are running into a connectivity issue.
I know this is an old question, but I would suspect a problem with ax25port - should be something like YOURCALL-0 where YOURCALL matches the HWaddr of an existing ax25 port ( try /sbin/ifconfig | fgrep AX.25

Resources