Silvio's blog

Berkeley API – Server in C + Client in PHP

  • Quinta-feira Jul 16,2009 07:18 PM
  • By admin
  • In IPv6

If you are a systems administrator responsible for hundreds of servers you may want to monitor them without login in every single server. The solution is quite easy, and the following code (based on my last two posts) can be easily adapted to your needs.

Objective

Remotely access to a box and execute a command without ssh or http on it.

server.c

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>

void newConnectionHandler(int sockd){
        FILE *stream;
        char buffer[100];
        int size;

        if((size = read(sockd, &buffer, 100)) < 1)
                perror("Unable to read from socket");
        buffer[size] = 0;

        if(strcmp(buffer, "uptime") == 0){
                stream = popen("uptime", "r");
                sleep(1);

                while(fgets(buffer, 2, stream) != NULL)
                        if(write(sockd, &buffer, strlen(buffer)) < 0)
                                perror("Unable to write on socket");

                pclose(stream);
        }
        else{
                strcpy(buffer, "Unknown command");
                if(write(sockd, &buffer, strlen(buffer)) < 0)
                        perror("Unable to write on socket");
        }
        close(sockd);
}

int main(int argc, char *argv[])
{
        int sockd,newsockd,tmpint;
        /* For IPv6
        struct sockaddr_in6 socketaddress;
        */
        /* For IPv4
        struct sockaddr_in socketaddress;
        */
        fd_set descriptorslist;
        struct timeval timeout;

        memset(&socketaddress,0,sizeof(socketaddress));
        /* For IPv6
        socketaddress.sin6_addr = in6addr_any;
        socketaddress.sin6_family = AF_INET6;
        socketaddress.sin6_port = htons(8000);
        */
        /* For IPv4
        socketaddress.sin_addr.s_addr = htonl(INADDR_ANY);
        socketaddress.sin_family = AF_INET;
        socketaddress.sin_port = htons(8000);
        */

        /* For IPv6
        if((sockd = socket(AF_INET6, SOCK_STREAM,0))<1){
        */
        /* For IPv4
        if((sockd = socket(AF_INET, SOCK_STREAM,0))<1){
        */
                perror("Unable to create socket");
                return 1;
        }

        // Bind socket sockfd on socketaddress
        if(bind(sockd, (struct sockaddr *)&socketaddress, sizeof(socketaddress)) != 0){
                perror("Unable to bind socket");
                return 1;
        }
        // Listen on socket, queue up to 10 connections
        if(listen(sockd,10) != 0){
                perror("Unable to listen on socket ");
                return 1;
        }

        // Clear the socket 'set'
        FD_ZERO(&descriptorslist);

        // Add sockd to fdread 'set'
        FD_SET(sockd, &descriptorslist);

        while(1){
                switch(select(32, &descriptorslist, NULL, NULL, &timeout)){
                        case -1:
                                perror("And error has ocurred");
                                break;
                        case 0:
                                printf("Timeout");
                                break;
                        default:
                                // Default, more than 0, number of descriptors on 'descriptorslist' ready
                                tmpint = sizeof(socketaddress);
                                // We fork an handler for the new connection (a new socket is passed as argument)
                                if(fork() == 0) // The above line is executed on child, where fork() == 0
                                {
                                        newConnectionHandler(accept(sockd,(struct sockaddr *)&socketaddress, &tmpint));
                                        exit(0);
                                }
                }
        }
}

remote.php

<?php

        // Create the socket
        /* FOR IPv6
        if(($sockd = @socket_create(AF_INET6, SOCK_STREAM,SOL_TCP))<1)
        */
        /* For IPv4
        if(($sockd = @socket_create(AF_INET, SOCK_STREAM,SOL_TCP))<1)
        */
                die("Unable to create socket:" . socket_strerror(socket_last_error()));

        // Bind socket sockfd on localaddress
        if(@socket_bind($sockd, "::1") == FALSE)
                die("Unable to bind socket:" . socket_strerror(socket_last_error()));

        if(@socket_connect($sockd,"SERVER_IP_HERE", 8000) == FALSE)
                die("Unable to connect:" . socket_strerror(socket_last_error()));

        $buffer = "1uptime";

        if(@socket_write($sockd, $buffer) < strlen($buffer))
                die("Unable to connect:" . socket_strerror(socket_last_error()));

        unset($buffer);

        if(($buffer = socket_read($sockd, 100)) == FALSE)
                die("Unable to read from socket:" . socket_strerror(socket_last_error()));

        socket_close($sockd);

        echo $buffer;

?>

, , , , , ,


2 Comments

  • svetozar diz:

    when i start server and remote i got a message in remote ” Unable to connect: Network is unreachable” ?

  • admin diz:

    Hi,
    I’ve updated the code, uncomment the *FOR IPv4* parts, you probabbly don’t have IPv6 connectivity


Leave a reply


XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Spam Protection by WP-SpamFree Plugin