static void add_connection(const char *path, DBusMessageIter *properties, void *user_data) { struct connection_data *data; int err; char *ident = get_ident(path); connman_bool_t found = FALSE; data = g_hash_table_lookup(vpn_connections, ident); if (data != NULL) { /* * We might have a dummy connection struct here that * was created by configuration_create_reply() so in * that case just continue. */ if (data->connect_pending == FALSE) return; found = TRUE; } else { data = create_connection_data(path); if (data == NULL) return; } DBG("data %p path %s", data, path); while (dbus_message_iter_get_arg_type(properties) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter entry, value; const char *key; char *str; dbus_message_iter_recurse(properties, &entry); dbus_message_iter_get_basic(&entry, &key); dbus_message_iter_next(&entry); dbus_message_iter_recurse(&entry, &value); if (g_str_equal(key, "State") == TRUE) { dbus_message_iter_get_basic(&value, &str); DBG("state %s -> %s", data->state, str); data->state = g_strdup(str); } else if (g_str_equal(key, "IPv4") == TRUE) { extract_ip(&value, AF_INET, data); } else if (g_str_equal(key, "IPv6") == TRUE) { extract_ip(&value, AF_INET6, data); } else if (g_str_equal(key, "Name") == TRUE) { dbus_message_iter_get_basic(&value, &str); data->name = g_strdup(str); } else if (g_str_equal(key, "Type") == TRUE) { dbus_message_iter_get_basic(&value, &str); data->type = g_strdup(str); } else if (g_str_equal(key, "Host") == TRUE) { dbus_message_iter_get_basic(&value, &str); data->host = g_strdup(str); } else if (g_str_equal(key, "Domain") == TRUE) { dbus_message_iter_get_basic(&value, &str); data->domain = g_strdup(str); } else if (g_str_equal(key, "Nameservers") == TRUE) { extract_nameservers(&value, data); } else if (g_str_equal(key, "Index") == TRUE) { dbus_message_iter_get_basic(&value, &data->index); } else { if (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { dbus_message_iter_get_basic(&value, &str); g_hash_table_replace(data->setting_strings, g_strdup(key), g_strdup(str)); } else { DBG("unknown key %s", key); } } dbus_message_iter_next(properties); } if (found == FALSE) g_hash_table_insert(vpn_connections, g_strdup(data->ident), data); err = create_provider(data, user_data); if (err < 0) goto out; resolv_host_addr(data); if (data->connect_pending == TRUE) connect_provider(data, data->cb_data); return; out: DBG("removing %s", data->ident); g_hash_table_remove(vpn_connections, data->ident); }
int connect_session(connection_data *connection, char *server_ip, uint16_t server_port, uint16_t client_port) { handshake_packet syn_packet, *received_packet = NULL; struct sockaddr_in server, client; socklen_t client_len; int i = 0, return_value = 0; char *ptr = NULL; char *client_ip = malloc(sizeof(char) * 16); uint32_t sock_fd = 0; srand(time(NULL)); net_init(); #ifdef _DEBUG_ printf("Before creating socket.\n"); #endif if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket() failed"); return -1; } #ifdef _DEBUG_ printf("After creating socket.\n"); printf("Creating sockaddr_in to find out client ip\n"); #endif memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(server_ip); server.sin_port = htons(server_port); #ifdef _DEBUG_ printf("Using a connected UDP socket to find out client ip\n"); #endif if (connect(sock_fd, (struct sockaddr *)&server, sizeof(server)) < 0) { perror("connect() failed (in trying to find out client ip)"); return -1; } client_len = sizeof(client); #ifdef _DEBUG_ printf("Using getsockname() to get local IP the socket bound to\n"); #endif if (getsockname(sock_fd, (struct sockaddr *)&client, &client_len) < 0) { perror("getsockname() failed when trying to find out client ip"); return -1; } #ifdef _DEBUG_ printf("Fetching the IP address from client sockaddr struct\n"); #endif if (inet_ntop(AF_INET, &client.sin_addr, client_ip, 16) < 0) { perror("inet_ntop() failed to get client ip"); return -1; } CLOSE(sock_fd); #ifdef _DEBUG_ printf("Client ip in buffer: %s\n", client_ip); printf("Before creating socket.\n"); #endif if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket() failed"); return -1; } #ifdef _DEBUG_ printf("After creating socket.\n"); printf("Preparing SYN packet.\n"); #endif syn_packet.proto_id = "herp"; syn_packet.packet_type = HANDSHAKE; syn_packet.client_ip = client_ip; syn_packet.client_port = client_port; syn_packet.client_id = rand(); syn_packet.flags = SYN; syn_packet.trailer = "derp"; #ifdef _DEBUG_ printf("Converting to string.\n"); #endif ptr = packet_to_string(&syn_packet, HANDSHAKE); #ifdef _DEBUG_ printf("Setting up listening socket.\n"); #endif connection = create_connection_data(client_ip, client_port, syn_packet.client_id, sock_fd, connection); #ifdef _DEBUG_ printf("Binding socket.\n"); #endif if (bind(connection->sock_fd, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("Bind() failed"); CLOSE(connection->sock_fd); return -1; } #ifdef _DEBUG_ printf("Creating connection_data.\n"); #endif connection = create_connection_data(server_ip, server_port, syn_packet.client_id, connection->sock_fd, connection); connection->client_ip = client_ip; connection->client_port = client_port; for(i = 0; i < 3; i++) { #ifdef _DEBUG_ printf("Try %d\n", i+1); printf("Struct data: %d %d %d socket: %d client_id: %d\n", connection->destination->sin_family, connection->destination->sin_port, connection->destination->sin_addr.s_addr, connection->sock_fd, connection->client_id); #endif if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("sendto() failed"); CLOSE(connection->sock_fd); return -1; } #ifdef _DEBUG_ printf("Entering listening mode.\n"); #endif ptr = listen_socket(connection, 5, 0); #ifdef _DEBUG_ if (ptr != NULL) printf("Received string: %s\n", ptr); #endif if (ptr != NULL) { if (atoi(&ptr[5]) == HANDSHAKE) { #ifdef _DEBUG_ printf("It is a handshake packet outside recv_data!\n"); #endif received_packet = (handshake_packet *)string_to_packet(ptr, HANDSHAKE); #ifdef _DEBUG_ printf("ptr size %d\n", strlen(ptr)); #endif if (!is_packet(received_packet, HANDSHAKE) && !strncmp(connection->client_ip, received_packet->client_ip, strlen(connection->client_ip)) && (received_packet->flags == ACK)) { #ifdef _DEBUG_ printf("ACK packet received: %p.\n", connection); #endif connection->client_id = received_packet->client_id; free(client_ip); return 0; } } else { #ifdef _DEBUG_ printf("Is not a packet :(\n"); #endif break; } } } fprintf(stderr, "No server responded with a ACK, stopping connection attempts...\n"); free(client_ip); return 1; }
static int create_configuration(DBusMessage *msg, connection_ready_cb callback) { DBusMessage *new_msg = NULL; DBusPendingCall *call; DBusMessageIter iter, array, new_iter, new_dict; const char *type = NULL, *name = NULL; const char *host = NULL, *domain = NULL; char *ident, *me = NULL; int err = 0; dbus_bool_t result; struct connection_data *data; struct config_create_data *user_data = NULL; GSList *networks = NULL; /* * We copy the old message data into new message. We cannot * just use the old message as is because the user route * information is not in the same format in vpnd. */ new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); dbus_message_iter_init_append(new_msg, &new_iter); connman_dbus_dict_open(&new_iter, &new_dict); dbus_message_iter_init(msg, &iter); dbus_message_iter_recurse(&iter, &array); while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter entry, value; void *item_value; const char *key; int value_type; dbus_message_iter_recurse(&array, &entry); dbus_message_iter_get_basic(&entry, &key); dbus_message_iter_next(&entry); dbus_message_iter_recurse(&entry, &value); value_type = dbus_message_iter_get_arg_type(&value); item_value = NULL; switch (value_type) { case DBUS_TYPE_STRING: dbus_message_iter_get_basic(&value, &item_value); if (g_str_equal(key, "Type") == TRUE) { type = (const char *)item_value; } else if (g_str_equal(key, "Name") == TRUE) { name = (const char *)item_value; } else if (g_str_equal(key, "Host") == TRUE) { host = (const char *)item_value; } else if (g_str_equal(key, "VPN.Domain") == TRUE) { domain = (const char *)item_value; } DBG("%s %s", key, (char *)item_value); if (item_value != NULL) connman_dbus_dict_append_basic(&new_dict, key, value_type, &item_value); break; case DBUS_TYPE_ARRAY: if (g_str_equal(key, "Networks") == TRUE) { networks = get_user_networks(&value); connman_dbus_dict_append_array(&new_dict, "UserRoutes", DBUS_TYPE_DICT_ENTRY, append_routes, networks); } break; } dbus_message_iter_next(&array); } connman_dbus_dict_close(&new_iter, &new_dict); DBG("VPN type %s name %s host %s domain %s networks %p", type, name, host, domain, networks); if (host == NULL || domain == NULL) { err = -EINVAL; goto done; } if (type == NULL || name == NULL) { err = -EOPNOTSUPP; goto done; } ident = g_strdup_printf("%s_%s", host, domain); set_dbus_ident(ident); DBG("ident %s", ident); data = g_hash_table_lookup(vpn_connections, ident); if (data != NULL) { if (data->call != NULL || data->cb_data != NULL) { DBG("create configuration call already pending"); err = -EINPROGRESS; goto done; } } else { char *path = g_strdup_printf("%s/connection/%s", VPN_PATH, ident); data = create_connection_data(path); g_free(path); if (data == NULL) { err = -ENOMEM; goto done; } g_hash_table_insert(vpn_connections, g_strdup(ident), data); } /* * User called net.connman.Manager.ConnectProvider if we are here. * So use the data from original message in the new msg. */ me = g_strdup(dbus_message_get_destination(msg)); dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE); dbus_message_set_path(new_msg, "/"); dbus_message_set_destination(new_msg, VPN_SERVICE); dbus_message_set_sender(new_msg, me); dbus_message_set_member(new_msg, "Create"); user_data = g_try_new0(struct config_create_data, 1); if (user_data == NULL) { err = -ENOMEM; goto done; } user_data->callback = callback; user_data->message = dbus_message_ref(msg); user_data->path = NULL; DBG("cb %p msg %p", user_data, msg); result = dbus_connection_send_with_reply(connection, new_msg, &call, DBUS_TIMEOUT); if (result == FALSE || call == NULL) { err = -EIO; goto done; } dbus_pending_call_set_notify(call, configuration_create_reply, user_data, NULL); data->call = call; done: if (new_msg != NULL) dbus_message_unref(new_msg); if (networks != NULL) g_slist_free_full(networks, destroy_route); g_free(me); return err; }
int accept_session (connection_data *connection, uint16_t port, int client_id) { handshake_packet ack_packet, *received_packet = NULL; static int first_time = 1; static uint16_t sock_fd; char *ptr = NULL; if (first_time) { #ifdef _DEBUG_ printf("Inside a first_time only\n"); #endif net_init(); #ifdef _DEBUG_ printf("Before creating socket.\n"); #endif if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { perror("socket() failed"); return -1; } #ifdef _DEBUG_ printf("After creating socket.\n"); #endif } connection = create_connection_data("0.0.0.0", port, 0, sock_fd, connection); if (first_time) { #ifdef _DEBUG_ printf("Setting up listening socket.\n"); printf("Binding socket.\n"); #endif if (bind(sock_fd, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("Bind() failed"); CLOSE(sock_fd); return -1; } first_time = 0; } while(1) { #ifdef _DEBUG_ printf("Listening for SYN packet.\n"); printf("connection->sock_fd: %d\n", connection->sock_fd); #endif ptr = listen_socket(connection, 60, 0); #ifdef _DEBUG_ printf("Received string: %s\n", ptr); #endif if (ptr != NULL) { if (atoi(&ptr[5]) == HANDSHAKE) { #ifdef _DEBUG_ printf("Converting from string to packet.\n"); #endif received_packet = (handshake_packet *)string_to_packet(ptr, HANDSHAKE); #ifdef _DEBUG_ printf("ptr size %d\n", strlen(ptr)); printf("It is a handshake packet outside recv_data!\n"); printf("Content: %s %u %s %u %u %s\n", received_packet->proto_id, received_packet->packet_type, received_packet->client_ip, received_packet->client_port, received_packet->flags, received_packet->trailer); #endif if (!is_packet(received_packet, HANDSHAKE) && received_packet->flags == SYN) { #ifdef _DEBUG_ printf("SYN Packet received.\n"); #endif break; } else if (!is_packet(received_packet, HANDSHAKE) && received_packet->flags == RST) { connection_termination(connection, SERVER); return 1; } } } } #ifdef _DEBUG_ printf("Preparing ACK packet.\n"); #endif ack_packet.proto_id = "herp"; ack_packet.packet_type = HANDSHAKE; ack_packet.client_ip = received_packet->client_ip; ack_packet.client_port = received_packet->client_port; ack_packet.client_id = client_id; ack_packet.flags = ACK; ack_packet.trailer = "derp"; #ifdef _DEBUG_ printf("Creating connection_data struct.\n"); #endif connection = create_connection_data(received_packet->client_ip, received_packet->client_port, client_id, connection->sock_fd, connection); #ifdef _DEBUG_ printf("Converting packet_to_string.\n"); #endif ptr = packet_to_string(&ack_packet, HANDSHAKE); #ifdef _DEBUG_ printf("Sending ACK packet.\n"); #endif if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("sendto() failed"); CLOSE(connection->sock_fd); return -1; } #ifdef _DEBUG_ printf("pointer address %p\n", connection); #endif free(received_packet); free(ptr); return 0; }