diff options
Diffstat (limited to 'src/debug/jdwp/tcp.c')
-rw-r--r-- | src/debug/jdwp/tcp.c | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/src/debug/jdwp/tcp.c b/src/debug/jdwp/tcp.c new file mode 100644 index 0000000..38acd29 --- /dev/null +++ b/src/debug/jdwp/tcp.c @@ -0,0 +1,328 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * tcp.c - gestion des connexions TCP aux serveurs JDWP. + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "tcp.h" + + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/types.h> + + +#include "packet.h" +#include "misc/header.h" +#include "sets/list.h" +#include "../stream-int.h" +#include "../../common/net.h" + + + +/* Flux de communication TCP avec un serveur JDWP (instance) */ +struct _GJdwpTcpClient +{ + GDebugStream parent; /* A laisser en premier */ + + char *server; /* Serveur à contacter */ + char *port; /* Port de connexion */ + int fd; /* Flux ouvert en L./E. */ + +}; + + +/* Flux de communication TCP avec un serveur JDWP (classe) */ +struct _GJdwpTcpClientClass +{ + GDebugStreamClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des flux de communication JDWP over TCP. */ +static void g_jdwp_tcp_client_class_init(GJdwpTcpClientClass *); + +/* Initialise une instance de flux de communication avec JDWP. */ +static void g_jdwp_tcp_client_init(GJdwpTcpClient *); + +/* Etablit de façon effective une connexion à la cible. */ +static bool g_jdwp_tcp_client_connect(GJdwpTcpClient *); + +/* Attend le signalement de données à traiter. */ +static bool g_jdwp_tcp_client_poll(GJdwpTcpClient *); + +/* Envoie un paquet de données à un serveur de débogage. */ +static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *, const GJdwpPacket *); + +/* Réceptionne un paquet de données d'un serveur de débogage. */ +static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *, GJdwpPacket *); + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur JDWP. */ +G_DEFINE_TYPE(GJdwpTcpClient, g_jdwp_tcp_client, G_TYPE_DEBUG_STREAM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des flux de communication JVDP over TCP.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_tcp_client_class_init(GJdwpTcpClientClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : client = instance à initialiser. * +* * +* Description : Initialise une instance de flux de communication avec JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_tcp_client_init(GJdwpTcpClient *client) +{ + GDebugStream *stream; /* Version parente */ + + stream = G_DEBUG_STREAM(client); + + stream->connect = (debug_connect_fc)g_jdwp_tcp_client_connect; + + stream->poll = (debug_poll_fc)g_jdwp_tcp_client_poll; + stream->send_packet = (debug_pkt_op_fc)g_jdwp_tcp_client_send_packet; + stream->recv_packet = (debug_pkt_op_fc)g_jdwp_tcp_client_recv_packet; + + stream->pkt_type = G_TYPE_JDWP_PACKET; + +} + + +/****************************************************************************** +* * +* Paramètres : server = nom ou adresse du serveur à contacter. * +* port = port de connexion. * +* * +* Description : Crée une nouvelle connexion TCP à un serveur JDWP. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDebugStream *g_jdwp_tcp_client_new(const char *server, const char *port) +{ + GJdwpTcpClient *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_JDWP_TCP_CLIENT, NULL); + + result->server = strdup(server); + result->port = strdup(port); + result->fd = -1; + + return G_DEBUG_STREAM(result); + +} + + +/****************************************************************************** +* * +* Paramètres : client = paramètres de connexion au serveur JDWP. * +* * +* Description : Etablit de façon effective une connexion à la cible. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_connect(GJdwpTcpClient *client) +{ + struct sockaddr_in addr; /* Infos de connexion distante */ + int sock; /* Flux ouvert à construire */ + char handshake[15]; /* Poignée de main chaleureuse */ + + sock = connect_via_tcp(client->server, client->port, &addr); + if (sock == -1) + { + printf("Echec de connexion au serveur JDWP sur %s:%s\n", + client->server, client->port); + return false; + } + + printf("Connecté à %s:%hd\n", client->server, ntohs(addr.sin_port)); + + if (send(sock, "JDWP-Handshake", 14, 0) != 14) + goto gjtcc_error; + + if (recv(sock, handshake, 14, 0) != 14) + goto gjtcc_error; + + if (strncmp(handshake, "JDWP-Handshake", 14) != 0) + goto gjtcc_error; + + client->fd = sock; + + return true; + + gjtcc_error: + + printf("Echec des premiers échanges !\n"); + + close(sock); + + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : client = paramètres de connexion au serveur JDWP. * +* * +* Description : Attend le signalement de données à traiter. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_poll(GJdwpTcpClient *client) +{ + bool result; /* Statut à faire remonter */ + fd_set rfds; /* Liste des flux à surveiller */ + int ret; /* Bilan d'un appel */ + + result = false; + + FD_ZERO(&rfds); + FD_SET(client->fd, &rfds); + + ret = select(client->fd + 1, &rfds, NULL, NULL, NULL); + + switch (ret) + { + case -1: + perror("select()"); + break; + + case 0: + /* ?! */ + break; + + default: + result = true; + break; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : client = flux ouvert en écriture à utiliser. * +* packet = zone mémoire à parcourir. * +* * +* Description : Envoie un paquet de données à un serveur de débogage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *client, const GJdwpPacket *packet) +{ + struct iovec iov[UIO_MAXIOV]; /* Table de vecteurs à écrire */ + int iovcnt; /* Quantité de champs valides */ + int i; /* Boucle de parcours */ + + g_debug_packet_vectorize(G_DEBUG_PACKET(packet), iov, &iovcnt); + + for (i = 0; i < iovcnt; i++) + if (send(client->fd, iov[i].iov_base, iov[i].iov_len, 0) != iov[i].iov_len) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : client = flux ouvert en lecture à utiliser. * +* packet = zone mémoire à remplir. [OUT] * +* * +* Description : Réceptionne un paquet de données d'un serveur de débogage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *client, GJdwpPacket *packet) +{ + bin_t *hblob; /* Contenu encodé en B.E. */ + jdwp_header *header; /* En-tête à reconstituer */ + uint32_t length; /* Taille de la charge utile */ + bin_t *pblob; /* Contenu encodé en B.E. */ + + hblob = g_jdwp_packet_get_hblob(packet); + + if (recv(client->fd, hblob, sizeof(jdwp_header), 0) != sizeof(jdwp_header)) + return false; + + if (!g_jdwp_packet_parse_header(packet)) + return false; + + header = g_jdwp_packet_get_header(packet); + length = header->length - sizeof(jdwp_header); + + pblob = g_jdwp_packet_get_pblob(packet); + + if (recv(client->fd, pblob, length, 0) != length) + return false; + + return true; + +} |