/**
 * 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 (&notify_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);
}
Exemple #6
0
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);
    }
}
Exemple #7
0
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;
}