/** * Send the given message to a particular client * * @param client target of the message * @param msg message to transmit * @param may_drop #GNUNET_YES if the message can be dropped */ void GST_clients_unicast (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int may_drop) { struct TransportClient *tc; tc = lookup_client (client); if (NULL == tc) return; /* client got disconnected in the meantime, drop message */ unicast (tc, msg, may_drop); }
/** * Create the internal handle for the given server client handle * * @param client server's client handle to create our internal handle for * @return fresh internal client handle */ static struct TransportClient * setup_client (struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; GNUNET_assert (NULL == lookup_client (client)); tc = GNUNET_new (struct TransportClient); tc->client = client; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc); return tc; }
/** * Called whenever a client is disconnected. Frees our * resources associated with that client. * * @param cls closure * @param client identification of the client */ static void client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; struct MonitoringClient *mc; struct ClientMessageQueueEntry *mqe; if (client == NULL) return; mc = lookup_monitoring_client (peer_monitoring_clients_head, client); if (mc != NULL) { GNUNET_CONTAINER_DLL_remove (peer_monitoring_clients_head, peer_monitoring_clients_tail, mc); GNUNET_free (mc); } mc = lookup_monitoring_client (val_monitoring_clients_head, client); if (mc != NULL) { GNUNET_CONTAINER_DLL_remove (val_monitoring_clients_head, val_monitoring_clients_tail, mc); GNUNET_free (mc); } tc = lookup_client (client); if (tc == NULL) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Client %p disconnected, cleaning up.\n", tc); while (NULL != (mqe = tc->message_queue_head)) { GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, mqe); tc->message_count--; GNUNET_free (mqe); } GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc); if (tc->th != NULL) { GNUNET_SERVER_notify_transmit_ready_cancel (tc->th); tc->th = NULL; } GNUNET_break (0 == tc->message_count); GNUNET_free (tc); }
/** * Initialize a normal client. We got a start message from this * client, add him to the list of clients for broadcasting of inbound * messages. * * @param cls unused * @param client the client * @param message the start message that was sent */ static void clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct StartMessage *start; struct TransportClient *tc; uint32_t options; tc = lookup_client (client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Client %p sent START\n", tc); if (tc != NULL) { /* got 'start' twice from the same client, not allowed */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "TransportClient %p ServerClient %p sent multiple START messages\n", tc, tc->client); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } start = (const struct StartMessage *) message; options = ntohl (start->options); if ((0 != (1 & options)) && (0 != memcmp (&start->self, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity)))) { /* client thinks this is a different peer, reject */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Rejecting control connection from peer `%s', which is not me!\n"), GNUNET_i2s (&start->self)); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } tc = setup_client (client); tc->send_payload = (0 != (2 & options)); unicast (tc, GST_hello_get (), GNUNET_NO); GST_neighbours_iterate (¬ify_client_about_neighbour, tc); GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Client asked for transmission to a peer. Process the request. * * @param cls unused * @param client the client * @param message the send message that was sent */ static void clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct OutboundMessage *obm; const struct GNUNET_MessageHeader *obmm; struct SendTransmitContinuationContext *stcc; uint16_t size; uint16_t msize; struct TransportClient *tc; tc = lookup_client (client); if (NULL == tc) { /* client asked for transmission before 'START' */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } size = ntohs (message->size); if (size < sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } obm = (const struct OutboundMessage *) message; obmm = (const struct GNUNET_MessageHeader *) &obm[1]; msize = size - sizeof (struct OutboundMessage); if (msize < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n", "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize); if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) { /* not connected, not allowed to send; can happen due to asynchronous operations */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not send message to peer `%s': not connected\n", GNUNET_i2s (&obm->peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload dropped (other peer was not connected)"), msize, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); stcc = GNUNET_new (struct SendTransmitContinuationContext); stcc->target = obm->peer; stcc->client = client; GNUNET_SERVER_client_keep (client); GST_manipulation_send (&obm->peer, obmm, msize, GNUNET_TIME_relative_ntoh (obm->timeout), &handle_send_transmit_continuation, stcc); }
void handle_dhcp(struct server_conf *conf, pcap_t *p, struct pktbuf *inpkt) { unsigned char tag, len; int i, j; int msgtype; union ip_address ip; unsigned char buffer[512]; guint32 lease; unsigned char *options = inpkt->dhcp_packet->options; unsigned char *srcmac = inpkt->eth_header->h_source; struct client_conf *client; #if DEBUG fprintf(stderr, "Optionslen: %d\n", inpkt->optlen); #endif if (inpkt->optlen < 6) return; #if DEBUG fprintf(stderr, "%d.%d.%d.%d\n", options[0], options[1], options[2], options[3]); #endif // check the magic cookie if (!(options[0] == 99 && options[1] == 130 && options[2]== 83 && options[3] == 99)) { return; } i = 4; while (1) { CHKOPTLEN(2); tag = options[i++]; if (tag == 0) continue; if (tag == 255) goto END; len = options[i++]; CHKOPTLEN(len); switch (tag) { case 1: // Subnet Mask if (len != 4) { fprintf(stderr, "Malformed len in subnet mask tag: Should be 4 but is %d\n", len); return; } ip.a[0] = options[i++]; ip.a[1] = options[i++]; ip.a[2] = options[i++]; ip.a[3] = options[i++]; printf("Subnet Mask: %d.%d.%d.%d\n", ip.a[0], ip.a[1], ip.a[2], ip.a[3]); break; case 3: // Default Gateway if (len < 4) { fprintf(stderr, "Malformed len in router tag: Should 4 or greater but is %d\n", len); return; } if (len % 4 != 0) { fprintf(stderr, "Malformed len in router tag: Should be a multiple of 4 but is %d\n", len); return; } len /= 4; for (j = 0; j < len; j++) { ip.a[0] = options[i++]; ip.a[1] = options[i++]; ip.a[2] = options[i++]; ip.a[3] = options[i++]; #if DEBUG printf("Router %d: %d.%d.%d.%d\n", j + 1, ip.a[0], ip.a[1], ip.a[2], ip.a[3]); #endif } break; case 6: // DNS Servers if (len < 4) { fprintf(stderr, "Malformed len in DNS tag: Should 4 or greater but is %d\n", len); return; } if (len % 4 != 0) { fprintf(stderr, "Malformed len in DNS tag: Should be a multiple of 4 but is %d\n", len); return; } len /= 4; for (j = 0; j < len; j++) { ip.a[0] = options[i++]; ip.a[1] = options[i++]; ip.a[2] = options[i++]; ip.a[3] = options[i++]; #if DEBUG printf("DNS Server %d: %d.%d.%d.%d\n", j + 1, ip.a[0], ip.a[1], ip.a[2], ip.a[3]); #endif } break; break; case 12: // Host Name Option memcpy(buffer, &options[i], len); buffer[len] = '\0'; #if DEBUG printf("Hostname: %s\n", buffer); #endif i += len; break; case 50: // Requested IP if (len != 4) { fprintf(stderr, "Malformed len in requested IP tag: Should be 4 but is %d\n", len); return; } ip.a[0] = options[i++]; ip.a[1] = options[i++]; ip.a[2] = options[i++]; ip.a[3] = options[i++]; printf("Requested IP: %d.%d.%d.%d\n", ip.a[0], ip.a[1], ip.a[2], ip.a[3]); break; break; case 51: // Lease Time in Seconds lease = *((guint32*) &options[i]); lease = ntohl(lease); printf("Lease: %ld\n", (long) lease); i += len; break; case 53: // DHCP Message Type msgtype = options[i++]; printf("MSG TYPE: %d\n", msgtype); printf("MSG TYPE: %s\n", msgtypes[msgtype]); break; case 54: // Server Identifier if (len != 4) { fprintf(stderr, "Malformed len in server identifier tag: Should be 4 but is %d\n", len); return; } ip.a[0] = options[i++]; ip.a[1] = options[i++]; ip.a[2] = options[i++]; ip.a[3] = options[i++]; printf("Server Identifier: %d.%d.%d.%d\n", ip.a[0], ip.a[1], ip.a[2], ip.a[3]); break; case 55: printf("DHCP options: "); for (j = 0; j < len; j++) { if (j != 0) printf(", "); printf("%d", options[i++]); } printf("\n"); break; default: fprintf(stderr, "ERROR: Unknown DHCP Option Tag: %d\n", tag); // skip over this tag i += len; } } END: // we serve only MACs we know fprintf(stderr, "Lookup of MAC %x:%x:%x:%x:%x:%x in VLAN %d\n", srcmac[0], srcmac[1], srcmac[2], srcmac[3], srcmac[4], srcmac[5], inpkt->vlan); client = lookup_client(conf, inpkt->vlan, srcmac); if (client == NULL) return; fprintf(stderr, "Lookup successful\n"); if (msgtype == DHCPDISCOVER) { send_offer(p, inpkt, client); } else if (msgtype == DHCPREQUEST) { send_ack(p, inpkt, client); } }
int server(int num_clients, int port) { WicServer server; wic_init_server(&server, port, num_clients); ClientData* clients = malloc(num_clients * sizeof(ClientData)); for(int i = 0; i < num_clients; i++) clients[i].joined = false; Command command; command.created = false; pthread_t command_thread; pthread_create(&command_thread, 0, accept_command, &command); printf("Type commands below...\n"); WicPacket recv; WicPacket send; while(true) { if(command.created == true) { if(strncmp(command.first_arg, "exit", 4) == 0) break; else if(strcmp(command.first_arg, "help") == 0) print_command_list(); else if(strcmp(command.first_arg, "kick") == 0) { ClientData* client = lookup_client(clients, command.second_arg, num_clients); if(client == 0) printf("ERROR: Client %s does not exist\n", command.second_arg); else wic_kick_client(&server, client->client_id); } else if(strcmp(command.first_arg, "ban-client") == 0) { ClientData* client = lookup_client(clients, command.second_arg, num_clients); if(client == 0) printf("ERROR: Client %s does not exist\n", command.second_arg); else wic_ban_client(&server, client->client_id); } else if(strcmp(command.first_arg, "ban-address") == 0) { wic_ban_address(&server, command.second_arg); } else if(strcmp(command.first_arg, "unban-address") == 0) { wic_unban_address(&server, command.second_arg); } else if(strcmp(command.first_arg, "ls-clients") == 0) { print_clients(clients, num_clients); } else printf("%s '%s'. %s", "ERROR: Invalid command", command.first_arg, "Type 'help' for command list\n"); command.created = false; pthread_create(&command_thread, 0, accept_command, &command); } enum WicError error = wic_server_recv_packet(&server, &recv); if(error == WICER_NONE) { unsigned char client_id = recv.client_id; if(recv.type.id == WIC_PACKET_JOIN.id) { clients[client_id].joined = true; clients[client_id].client_id = client_id; init_entity_manager(&clients[client_id].manager); printf("client %u joined\n", client_id); } if(recv.type.id == PACKET_USERNAME_INFO.id) { memcpy(clients[client_id].username, recv.data, PACKET_USERNAME_INFO.size); wic_send_packet_to_other_clients(&server, &recv, client_id); for(unsigned char id = 0; id < num_clients; id++) { if(clients[id].joined && id != client_id) { send.type = PACKET_USERNAME_INFO; send.client_id = id; memcpy(send.data, clients[id].username, sizeof(clients[id].username)); wic_send_packet_to_client(&server, &send, client_id); } } } else if(recv.type.id == WIC_PACKET_LEAVE.id) { clients[client_id].joined = false; free_entity_manager(&clients[client_id].manager); printf("client %u left\n", recv.client_id); } else if(recv.type.id == PACKET_UPDT_ENTITY.id) { Entity entity; memcpy(&entity, recv.data, PACKET_UPDT_ENTITY.size); updt_entity(&clients[client_id].manager, entity); wic_send_packet_to_other_clients(&server, &recv, client_id); } else if(recv.type.id == PACKET_REMV_ENTITY.id) { remove_entity(&clients[client_id].manager, recv.data[0]); wic_send_packet_to_other_clients(&server, &recv, client_id); } } } printf("Exiting server..\n"); wic_free_server(&server); return 0; }