#include #include #include #include #include #include "ildus-connection.h" #include "ildus-manager.h" #define ILDUS_OKAY 200 #define ILDUS_WELCOME 220 #define ILDUS_GOODBYE 221 #define ILDUS_AUTHENTICATED 230 #define ILDUS_UPATE_OK 240 #define ILDUS_USER_OKAY 331 typedef struct { char *server; int port; char *hostname; char *username; char *password; } ildus_manager_t; ildus_manager_t *manager; static void _ildus_print_message(ildus_message_t *m) { if (m->long_msg) { int i; printf("<+%s\n", m->head_msg); for (i = 0; m->data[i] != NULL; i++) { printf("{+%s\n", m->data[i]); } } printf("<<%s\n", m->msg); } static int _ildus_send_message(ildus_connection_t *c, char *format, ...) { #define BUFSIZE 1024 char buffer[BUFSIZE]; va_list ap; int n; va_start(ap , format); n = vsnprintf(buffer, BUFSIZE - 1, format, ap); va_end(ap); if (n < 0 || n > BUFSIZE - 1) { return -1; } printf(">>%s", buffer); return ildus_connection_send(c, buffer); } static int _ildus_get_message(ildus_connection_t *con, int replycode, ildus_connection_error_t *error) { ildus_message_t *msg = NULL; int ret = TRUE; msg = ildus_connection_get_message(con, error); if (msg == NULL) { printf("Failed to get message\n"); return FALSE; } _ildus_print_message(msg); if (msg->code != replycode) { fprintf(stderr, "Unexpected reply from ildus server received (%d != %d)\n", msg->code, replycode); ret = FALSE; } del_ildus_message(msg); return ret; } int ildus_manager_do_update(address_t *v4, address_t *v6) { #define GET_MESSAGE(replycode) \ do { if (!_ildus_get_message(con, replycode, &error)) \ goto error; \ } while(0) #define SEND_MESSAGE(...) \ do { \ if (!_ildus_send_message(con, __VA_ARGS__)) { \ fprintf(stderr, "Failed to send data to ildus server\n"); \ goto error; \ } \ } while(0) ildus_connection_t *con = NULL; ildus_connection_error_t error = ILDUS_CONNECTION_CONNECTION_NO_ERROR; int ret = TRUE; if (v4 && v4->current) { v4 = NULL; } if (v6 && v6->current) { v6 = NULL; } if (v4 == NULL && v6 == NULL) { /* Nothing to do */ return TRUE; } /* We need to update at least one address */ con = new_ildus_connection("ildus.luon.net", 9000, &error); if (con == NULL) { goto error; } /* First we receive the welcome */ GET_MESSAGE(ILDUS_WELCOME); /* Send username */ SEND_MESSAGE("USER %s\r\n", manager->username); GET_MESSAGE(ILDUS_USER_OKAY); /* Password */ SEND_MESSAGE("PASS %s\r\n", manager->password); GET_MESSAGE(ILDUS_AUTHENTICATED); /* Update when needed */ if (v4) { char buffer[INET6_ADDRSTRLEN]; inet_ntop(v4->family, &(v4->a.v4), buffer, INET6_ADDRSTRLEN); SEND_MESSAGE("UPDT %s %s\r\n", manager->hostname, buffer); if (_ildus_get_message(con, ILDUS_UPATE_OK, &error)) { address_toggle_current(v4); } else if (error == ILDUS_CONNECTION_CONNECTION_NO_ERROR) { /* We didn't get the ILDUS_UPATE_OK reply */ fprintf(stderr, "Failed to update IPv4 address\n"); ret = FALSE; } else { goto error; } } if (v6) { char buffer[INET6_ADDRSTRLEN]; inet_ntop(v6->family, &(v6->a.v6), buffer, INET6_ADDRSTRLEN); SEND_MESSAGE("UPDT %s %s\r\n", manager->hostname, buffer); if (_ildus_get_message(con, ILDUS_UPATE_OK, &error)) { address_toggle_current(v6); } else if (error == ILDUS_CONNECTION_CONNECTION_NO_ERROR) { /* We didn't get the ILDUS_UPATE_OK reply */ fprintf(stderr, "Failed to update IPv6 address\n"); ret = FALSE; } else { goto error; } } /* and quit */ SEND_MESSAGE("QUIT\r\n"); GET_MESSAGE(ILDUS_GOODBYE); del_ildus_connection(con); return ret; error: switch (error) { case ILDUS_CONNECTION_CONNECTION_NO_ERROR: /* No need to print, something else caused it (wrong replycode ?) */ break; case ILDUS_CONNECTION_CONNECTION_READ_ERROR: fprintf(stderr, "Connection to ildus server closed unexpectedly\n"); break; case ILDUS_CONNECTION_CONNECTION_BUFFER_OVERFLOW: fprintf(stderr, "Received line from ildus server too long\n"); break; case ILDUS_CONNECTION_UNRESOLVED_HOST_ERROR: fprintf(stderr, "Couldn't resolve: %s\n", manager->server); break; case ILDUS_CONNECTION_FAILED: fprintf(stderr, "Failed to connect to ildus server: [%s]:%d\n", manager->server, manager->port); break; case ILDUS_CONNECTION_MALFORMED_REPLY: fprintf(stderr, "Got malformed reply from ildus server\n"); break; fprintf(stderr,"Unknown error %d\n", error); } del_ildus_connection(con); return FALSE; } void ildus_manager_init(char *server, int port, char *username, char *password, char *hostname) { manager = malloc(sizeof(ildus_manager_t)); manager->server = strdup(server); manager->port = port; manager->username = strdup(username); manager->password = strdup(password); manager->hostname = strdup(hostname); }