I'm programming a simple Load Balancer as part of a course, and in order to inform the servers and browser of the ports I bind to, I save them as a simple file in the same directory, which they can then read. The issue is that even though both ports i'm creating are using the same function, one of the files is not being created. I've gone over the code over and over and I cannot find the issue.
Basically, only the file http_port is being created.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include "LB.h"
int main() {
srand(time(NULL));
int i, server_socket, http_socket, client_socket, servers[3];
char *server_port = "server_port", *http_port = "http_port";
http_socket = Get_Socket(http_port);
server_socket = Get_Socket(server_port); //continues to load balancer
//inside functions.c
int Get_Socket(char* filename)
{
int port, bind_state = -1;
int new_socket;
struct sockaddr_in socket_address;
socket_address.sin_family = AF_INET;
socket_address.sin_addr.s_addr = INADDR_ANY;
do
{
port = get_random_port(PORT_MIN, PORT_MAX);
socket_address.sin_port = htons(port);
new_socket = socket(AF_INET, SOCK_STREAM, 0);
bind_state = bind(new_socket, (struct sockaddr*) &socket_address, sizeof(socket_address));
} while (bind_state < 0);
Write_Port2File(filename, port);
return new_socket;
}
void Write_Port2File(char* filename, int port)
{
printf("%s", filename);
FILE* fp = fopen(filename, "w");
if (fp == NULL)
exit(1);
fprintf(fp, "%d", port);
fclose(fp);
}
I'd appreciate any and all advice you can provide towards solving this issue.
P.S. It seems the problem only occurs after I enable the permissions for the folder with chmod 755 * and chmod 777 . (which is part of the course requirements).
Thank you in advance.
Related
I am having a serious problem transferring my HTTP connection socket program over to HTTPS connection socket code, how do I make only an HTTPS connection in pure C?
I am working on a package manager and am rewriting the connection.c file, the only thing this file contains is the code used to make the initial connection to the server containg packages, it does nothing else. I had this working 100% with an HTTP connection, however I need to move to an HTTPS connection and need to use LibreSSL; at the moment I am trying to use OpenSSL as I can't find anything on LibreSSL. The HTTP code I had is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include "repos.h"
#include "resolv.h"
short connection()
{
short socket_desc;
socket_desc = socket(AF_INET, SOCK_STREAM, 0); /* create socket with IPv4 and TCP protocol */
char host[17];
if (socket_desc == -1)
printf("could not create socket\n");
struct sockaddr_in *serv_addr = calloc(1, sizeof(struct sockaddr_in));
serv_addr->sin_family = AF_INET;
serv_addr->sin_port = htons(80);
resolv(DEFAULT_HOST, host); /* set repository to use */
if (inet_pton(AF_INET, host, &serv_addr->sin_addr) <= 0) {
printf("error");
free(serv_addr);
return -1;
}
if (connect(socket_desc, (struct sockaddr *)serv_addr, sizeof(*serv_addr)) < 0) {
printf("connection failed\n");
return 1;
}
else {
printf("connection initialized\n");
return 0;
}
/* close the connection */
free(serv_addr);
close(socket_desc);
return 0;
}
This works 100% and I want to just port this over to HTTPS. After looking at the horribly formatted OpenSSL client.c example (see here: https://wiki.openssl.org/index.php/SSL/TLS_Client) I got that code working on my system (had to make some changes to it), and then went off to port over my HTTP code to HTTPS. I worked on it for a bit and thought I got it working, I have been debugging it but can't figure out why it keeps failing. The code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "repos.h"
#include "resolv.h"
SSL *cSSL;
void initssl()
{
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
}
void destroyssl()
{
ERR_free_strings();
EVP_cleanup();
}
void shutdownssl()
{
SSL_shutdown(cSSL);
SSL_free(cSSL);
}
int main()
{
short socket_desc;
short socket_ssl;
char host[17];
socklen_t sock_size;
SSL_CTX *sslctx;
initssl();
socket_desc = socket(AF_INET, SOCK_STREAM, 0); /* create socket with IPv4 and TCP protocol */
if (socket_desc == -1)
printf("could not create socket\n");
struct sockaddr_in *serv_addr = calloc(1, sizeof(struct sockaddr_in));
serv_addr->sin_family = AF_INET;
serv_addr->sin_port = htons(443);
resolv(DEFAULT_HOST, host); /* resolve DEFAULT_HOST and store the ip in host */
if (inet_pton(AF_INET, host, &serv_addr->sin_addr) <= 0) {
printf("error");
free(serv_addr);
return -1;
}
bind(socket_desc, (struct sockaddr *)serv_addr, sizeof(struct sockaddr_in));
listen(socket_desc, 5);
sock_size = sizeof(struct sockaddr_in);
socket_ssl = accept(socket_desc, (struct sockaddr *)serv_addr, &sock_size); /* this is where hang occurs, however I am usnure why. I am reading docs and such and if I figure this out I will post the fix; however I would love some advice/help if anyone sees my error */
sslctx = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
short use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);
short use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);
cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, socket_ssl);
char ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0) {
printf("connection failed\n");
shutdownssl();
}
else
printf("connected\n");
return 0;
}
Now I know it is missing some obvious things such as writing my own initssl (I am unsure why that isn't already in the lib, but I am starting to see why OpenBSD decided to fork). I left those out as I am more interested in this working with LibreSSL and don't believe you need them with LibreSSL. I tried using print statements to debug but they never get printed even when given at the top of main(). I am unsure why this isn't working and need some help getting this ported. The other files I wrote, repos.h and resolv.c can be seen below:
/* repos.h */
char DEFAULT_HOST[11] = "gitlab.com";
char DEFAULT_PAGE[24] = "Puffles_the_Dragon/core";
/* resolv.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
short resolv(char *host, char *ip)
{
struct hostent *hp = calloc(1, sizeof(struct hostent));
hp = gethostbyname(host);
if (hp == NULL) {
fprintf(stderr, "gethostbyname() failed\n");
exit(1);
}
else {
short i = 0;
while (hp->h_addr_list[i] != NULL) {
inet_ntoa(*(struct in_addr *)(hp->h_addr_list[i]));
i++;
}
strlcpy(ip, inet_ntoa(*(struct in_addr *)(hp->h_addr_list[0])), 16);
}
return 0;
}
I know some of these calls are outdated due to IPv6, but I am going to add for IPv6 after I get this all working and port from BSD libc to musl libc.
I expected the HTTPS code to run and connect to the server thus printing connected, but it just runs and doesn't fail or print anything.
I am trying to write a simple file transfer between sockets in C. My client code looks like this:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv){
int sockfd, n;
struct sockaddr_in servaddr;
sockfd=socket(AF_INET,SOCK_STREAM,0);
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(22000);
inet_pton(AF_INET, "127.0.0.1", &(servaddr.sin_addr));
connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
FILE* fp;
fp = fopen("text.txt", "r");
sendfile(sockfd, fp, NULL, 100);
}
And my server code looks like this:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(22000);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
int bytes;
char rec[100];
FILE * fp;
fp = fopen("random.txt", "w");
while((bytes = read(comm_fd, rec, 100)) > 0){
fwrite(rec, 1, bytes, fp);
}
}
As you can see, I am sending text.txt file to server from client. Then on server, I try to read it and put the contents in random.txt in while loop but when I execute them, client finishes working, server doesn't stop working and nothing is written in random.txt.
Can you suggest why?
sendfile expects a file descriptor as the second argument, not a FILE *. If you included all necessary header files in your code you would get the corresponding error messages during the compilation.
To get a file descriptor open the file with open, i.e. replace lines
FILE* fp;
fp = fopen("text.txt", "r");
with
int fp;
fp = open("text.txt", O_RDONLY);
Also, for a production version, do not forget to check for error return values of functions like open, connect, bind, ... and to close files and sockets when you do not use them anymore.
I'm trying to use a mavlink sample developed by Parrot to control a Bebop2 using mavlink protocol (link here).
In order to send a message to the drone, they use the sendto function but I encounter an issue I cannot resolve : everytime I try to make the program works, I recieve an error and after a bit of investigation, I found that it's the 'sendto' used in this code (in the mavlink_comm_send_msg function) that returns an EINVAL error type (code located inside the mavlink_comm.c file in the src directory) :
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <poll.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <mavlink.h>
#include "mavlink_comm.h"
#define MAVLINK_COMM_BUFSIZE 4096
struct mavlink_comm {
int sock;
struct sockaddr_in remote_addr;
unsigned char tx_buffer[MAVLINK_COMM_BUFSIZE];
unsigned int tx_bufidx;
unsigned char rx_buffer[MAVLINK_COMM_BUFSIZE];
unsigned int rx_bufidx;
void (*cb)(mavlink_message_t *msg, void *user_data);
void *user_data;
};
struct mavlink_comm *mavlink_comm_new(struct mavlink_comm_cfg *cfg)
{
struct sockaddr_in locAddr;
struct mavlink_comm *c;
struct hostent *server;
if (!cfg)
return NULL;
c = calloc(1, sizeof(*c));
if (!c)
return NULL;
c->cb = cfg->cb;
c->user_data = cfg->user_data;
c->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset(&locAddr, 0, sizeof(locAddr));
locAddr.sin_family = AF_INET;
locAddr.sin_addr.s_addr = INADDR_ANY;
locAddr.sin_port = htons(cfg->local_port);
if (cfg->remote_addr && cfg->remote_addr[0] != '\0') {
server = gethostbyname(cfg->remote_addr);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host %s\n",
cfg->remote_addr);
exit(0);
}
bzero((char *) &c->remote_addr, sizeof(c->remote_addr));
c->remote_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&c->remote_addr.sin_addr.s_addr,
server->h_length);
c->remote_addr.sin_port = htons(cfg->remote_port);
}
/* Bind the socket to port 14551
* necessary to receive packets from qgroundcontrol */
if (-1 == bind(c->sock,(struct sockaddr *)&locAddr,
sizeof(struct sockaddr))) {
perror("error bind failed");
goto exit_close;
}
return c;
exit_close:
close(c->sock);
free(c);
return NULL;
}
static inline int mavlink_comm_send_data_internal(struct mavlink_comm *c)
{
int size = sizeof(struct sockaddr_in);
return sendto(c->sock, c->tx_buffer, c->tx_bufidx, 0,
(struct sockaddr*)&c->remote_addr,
sizeof(struct sockaddr_in));
}
int mavlink_comm_send_msg(struct mavlink_comm *c, mavlink_message_t *msg)
{
if (!c || !msg)
return -EINVAL;
int len = mavlink_msg_to_send_buffer(c->tx_buffer, msg);
return sendto(c->sock, c->tx_buffer, len, 0,
(struct sockaddr*)&c->remote_addr,
sizeof(struct sockaddr_in));
}
I looked at other related posts and tried several things to make it work but none of them were successful. The cast seems correct and I verified dest_len argument, so I'm quite lost.
Thanks a lot for your help.
I would like to connect to a mail server to read the mail. For example, I have an outlook address toto#outlook.com, and I want to get all the mail of this mailbox and be able to read it. So I believe I only have to do a client, but : How do I contact and connect to this type of servers, and how do I listen the answer?
Here is my current client code :
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int main()
{
struct protoent *pe;
int fd_client;
struct sockaddr_in s_in;
int port;
char *ip;
char buff[4096];
ip = strdup("157.56.242.251"); // I get it while calling "ping outlook.com"
port = 210;
pe = getprotobyname("TCP");
fd_client = socket(AF_INET, SOCK_STREAM, pe->p_proto);
s_in.sin_family = AF_INET;
s_in.sin_port = htons(port);
s_in.sin_addr.s_addr = inet_addr(ip);
if (connect(fd_client, (struct sockaddr *)&s_in, sizeof(s_in)) == -1)
{
if (close(fd_client) == -1)
return (-1);
fprintf(stderr, "Failed to connect\n");
return (-1);
}
//From here I don't know what to do, so I tried this
recv(fd_client, buff, 4096, 0);
printf("%s\n",buff);
write(fd_client, "Hello !\n", strlen("Hello !\n"));
//To Here
if (close(fd_client) == -1)
return (-1);
return (0);
}
Thanks in advance.
I need to make a custom port scanner that scan only opened TCP and UDP ports. I'm working in standard C with sockets. For the moment i retrieve all ports in a range i set.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
int scanPort(struct hostent *hostaddr,int port){
char responce[1024];
char *message="checking port";
struct sockaddr_in server_address;
int socket_d;
int rval;
socket_d = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(socket_d == -1)
{
perror("Socket()\n");
return errno;
}
memset(&server_address,0,sizeof(server_address));
server_address.sin_family=AF_INET;
server_address.sin_port=htons(port);
memcpy(&server_address.sin_addr,hostaddr->h_addr,hostaddr->h_length);
rval = connect(socket_d,(struct sockaddr *) &server_address, sizeof(server_address));
if(rval == -1)
{
close(socket_d);
return 0;
}else{
close(socket_d);
return 1;
}
}
int main(int argc, char **argv)
{
if(argc < 4){
printf("Exemplu: ./portscanner <adresa_ip> <port_pornire> <port_oprire> \n");
return (EINVAL);
}
int startPort;
int endPort;
int port;
struct hostent *host_address;
host_address = gethostbyname( argv[1] );
startPort = atoi(argv[2]);
endPort = atoi(argv[3]);
for(port = startPort;port<=endPort;port++)
{
if(scanPort(host_address,port)==1){
printf("Port %d is open\n",port);
}
}
}
In the example you can see how i tried to resolve this problem. But i don't see a method to check only the TCP and UDP ports. Please help me with this.
Regards,
Badea Sorin!
There is a plenty ways to do it. I recommend you to install nmap and read the manual.
Many scan methods are implemented there and described in the manual.
You can also refer to the source code if you need more details.
Good luck.