linux socket accept can't been blocked - linux

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
int main()
{
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
create a new socket
unlink("server_socket");
server_sockfd=socket(AF_INET,SOCK_STREAM,0);
name it
server_address.sin_family=AF_INET;
server_address.sin_addr.s_addr=htonl(INADDR_ANY);
server_address.sin_port=htons(9734);
server_len=sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_len);
set block
int flags=fcntl(server_sockfd,F_GETFL,0);
if(flags&O_NONBLOCK==1){
printf("NONBLOCK");
}else{
printf("BLOCK");
}
flags=flags&~O_NONBLOCK;
fcntl(server_sockfd,F_SETFL,flags);
if(flags&O_NONBLOCK==1){
printf("NONBLOCK");
}else{
printf("BLOCK");
}
listen
listen(server_sockfd,5);
while(1){
char ch;
printf("server waiting\n");
client_len=sizeof(client_address);
client_sockfd=
accept(server_sockfd,(struct sockaddr*)&client_sockfd,&client_len);
it is blocked at first time
read(client_sockfd,&ch,1);
ch++;
write(client_sockfd,&ch,1);
close(client_sockfd);
}
}
when the client connected first,I work,but the next won't work

A mismatch may occurs between client_address and client_sockfd.
The man page of accept() says:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
The addrlen argument is a value-result argument: the caller must initialize it to
contain the size (in bytes) of the structure pointed to by addr; on return it
will contain the actual size of the peer address.
Try:
client_sockfd=
accept( server_sockfd, (struct sockaddr*)&client_address, &client_len );

Related

NETLINK_NFLOG support in Linux 4.14

I've this program which runs fine on Linux 2.6.34. While porting this program to 4.14, socket creation is giving error "Error: : Protocol not supported". As per http://man7.org/linux/man-pages/man7/netlink.7.html
NETLINK_NFLOG (up to and including Linux 3.16)
Netfilter/iptables ULOG.
Do we know what is the alternative in 4.14 ?
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <pthread.h>
#include <netinet/ip.h>
#include <linux/types.h>
#include <linux/netlink.h>
int main()
{
struct sockaddr_nl addr;
int mypid;
int status;
int sockfd = -1;
/* mypid = getpid(); */
mypid = pthread_self();
sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NFLOG);
if (sockfd <= 0) {
printf("netlink socket() failed - rc:%d, errno:%d\n",
sockfd, errno);
perror("Error: ");
return (-1);
}
/* set up socket address */
memset(&addr, 0, sizeof (addr));
addr.nl_pid = mypid;
addr.nl_family = AF_NETLINK;
/*
nl_groups is the multicast
group ID to which the ULOG
messages will be sent.It
is bitmap of hexadecimal
format
*/
addr.nl_groups = 1;
/* bind socket to listen on
* multicast group 1 */
status = bind(sockfd, (struct sockaddr *)&addr, sizeof (addr));
if (status < 0) {
perror("bind:");
close(sockfd);
return (-1);
}
printf("socket bind successful\n");
close(sockfd);
return (0);
}
I tried to browse kernel source but couldn't identify.
I've below config
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_ADVANCED is not set
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_LOG=y
# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set
CONFIG_NETFILTER_XTABLES=y
CONFIG_NETFILTER_XT_MARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_NAT=y
# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
NETLINK_NFLOG (up to and including Linux 3.16)
see worked example in libnml

setsockopt IPT_SO_SET_REPLACE flag return error (linux)

I try to use setsockopt with the flag IPT_SO_SET_REPLACE but i keep getting the wired error from errno Protocol not available this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <fcntl.h>
int main(void) {
int sock;
int ret;
void *data;
size_t size;
struct ipt_replace *repl;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("socket");
return -1;
}
size = sizeof(struct ipt_replace);
data = malloc(size); Protocol not available
if (data == NULL) {
perror("malloc");
return -1;
}
memset(data, 0, size);
repl = (struct ipt_replace *) data;
repl->num_counters = 0x1;
repl->size = 0xffffffff;
repl->valid_hooks = 0x1;
repl->num_entries = 0x1;
ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, size);
printf("\ndone %d\n", ret);
perror("error: ");
return 0;
}
this is the output :
sock:3
data:
size:92
done -1
error: : Protocol not available
Looking briefly at the kernel code, this would seem to indicate that the IP tables module isn't available (i.e. the kernel wasn't built with it configured, or it can't be found or loaded).
It appears to me that for a socket of the kind you created, the code flow is:
enter raw_setsockopt: level != SOL_RAW so...
call ip_setsockopt: level == SOL_IP but option isn't any of the IP_xxx options so...
call nf_setsockopt: Search loaded netfilter modules for one that has registered IPT_SO_SET_REPLACE.
I think the last must have failed, so you get ENOPROTOOPT back (== Protocol not available)

Send dns queryis over ssl

I need to dns over ssl. DNS queryis UDP packeted and I need to change it to SSL protocol?
It is working in linux.
How does ubuntu 12.04 resolves dns and how to change to SSL?
I have tried create ssl socket and send dns queryis.
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netdb.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
//#include "server.h"
#define FAIL -1
void initChild(int cli, SSL_CTX* ctx);
void error(const char *msg) {
perror(msg);
exit(1);
}
int main(int count, char *strings[]) {
SSL_CTX *ctx;
int server;
char *portnum;
SSL* ssl;
int cli;
struct hostent *hp;
int pid;
if (count != 2)
{
printf("Usage: %s <portnum>\n", strings[0]);
exit(0);
}
SSL_library_init();
portnum = strings[1];
ctx = InitServerCTX();
LoadCertificates(ctx, "ser-cert.pem", "ser-key.pem");
server = OpenListener(atoi(portnum));
while (1) {
struct sockaddr_in addr;
int len = sizeof(addr);
int cli = accept(server, (struct sockaddr*)&addr, &len);
if (!(pid = fork())) {
//Child process
//close(server);
initChild(cli, ctx);
exit(0);
}
else if (pid > 0) {
//Parent process
}
else {
printf("Fork failed!!");
//close(server);
}
}
close(server);
SSL_CTX_free(ctx);
return 0;
}
void initChild(int cli, SSL_CTX* ctx) {
SSL* ssl;
ssl = SSL_new(ctx);
SSL_set_fd(ssl, cli);
DnsData(ssl);
}
This works in terminal mode. Now I need to change terminal mode to GUI mode. GUI mode is web browser. This code uses ssl certificate generated by me. How to write simple ssl dns queried web browser in c?

UDP Server giving Segmentation Fault

Ive written the following echo server using UDP but i have no idea that why it is giving me Segmentation Fault in sendto function, it receives fine but has problem sending data back to client. Ive been trying to find the problem for a few hours now but got no where. Can somebody please point out the fault or what i may be doing wrong.
Thanks
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
int main(int argc,char **args)
{
int BUF_LENGTH=101;
int port_no=1800;
struct sockaddr_in serv_addr,rmt_addr;
//rmt_addr=malloc(sizeof(struct sockaddr_in));
char *buffer=malloc(BUF_LENGTH);
int byte_recv=0;
int rmt_length=0;
int sock_id;
sock_id=socket(AF_INET,SOCK_DGRAM,0);
if(sock_id<0)
{
printf("Error creating socket : %d",sock_id);
return -1;
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(port_no);
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(sock_id,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
printf("Created\n");
while(true)
{
printf("Waiting\n");
byte_recv=recvfrom(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,&rmt_length);
printf("%s\n",buffer);
if(byte_recv<0)
{
printf("Error receiving: %d",byte_recv);
error("recvfrom");
return -2;
}
printf("%d:%d %s\n",rmt_length,rmt_addr.sin_port,inet_ntoa(rmt_addr.sin_addr));
byte_recv=sendto(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,rmt_length); //The segmentation fault comes here
printf("Bytes sent: %d \n",byte_recv);
if(byte_recv<0)
error("sendto");
}
free(buffer);
return 0;
}
These lines:
error("recvfrom");
error("sendto");
don't do what you think they do. You probably meant to say perror.
Additionally, you aren't initializing rmt_length correctly. Try this:
int rmt_length=sizeof(rmt_addr);
Finally, you are echoing more bytes back than the server receives. Try this:
byte_recv=sendto(sock_id,buffer,byte_recv,0,(struct sockaddr*)&rmt_addr,rmt_length);

Linux sockets communicating with QTcpSockets in Qt 4

I am trying to communicate with TCP between a Qt program and a regular linux program. I have an existing linux client server program and I am trying to replace the server program with a Qt application. Here is the linux client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
portno = 9876;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("ERROR opening socket");
return -1;
}
server = gethostbyname("localhost");
if (server == NULL)
{
printf("ERROR, no such host\n");
return -1;
}
memset((char *) &serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr));
sprintf(buffer,"This is a test\n");
n = write(sockfd,buffer,256);
return 0;
}
Here is the qt code
#include <Qt>
#include <QApplication>
#include <QTcpServer>
#include <QMessageBox>
#include <QTcpSocket>
#include <QtNetwork>
#include "qtserver.h"
Server::Server()
{
tcp = new QTcpServer(this);
tcp->listen(QHostAddress::Any,9876);
QObject::connect(tcp,SIGNAL(newConnection()),this,SLOT(printline()));
}
void Server::printline()
{
QTcpSocket *client = tcp->nextPendingConnection();
QObject::connect(client,SIGNAL(disconnected()),
client,SLOT(deleteLater()));
QDataStream in(client);
in.setVersion(QDataStream::Qt_4_0);
QString data;
in >> data;
printf("String = %s\n",(char*)data.data());
}
int main(int argc,char** argv)
{
QApplication a(argc,argv);
Server* server = new Server();
return a.exec();
}
When i try to run both of them I just get "String = " instead of the string outputting. Any idea what I'm doing wrong?
QString::data() returns QChar*, you can't just cast it to char* and hope that it would always work. For debugging QString, use qPrintable instead.
Also, QTcpSocket is very easy to use. Still, instead of writing the code from scratch, why not start by checkout out the examples, e.g. Fortune Server example.

Resources