예제 #1
0
void udpEchoTask(void *param)
{
   error_t error;
   uint_t length;
   uint16_t port;
   IpAddr ipAddr;
   EchoServiceContext *context;

   //Get a pointer to the context
   context = (EchoServiceContext *) param;

   //Main loop
   while(1)
   {
      //Wait for an incoming datagram
      error = socketReceiveFrom(context->socket, &ipAddr, &port,
         context->buffer, ECHO_BUFFER_SIZE, &length, 0);

      //Any datagram received?
      if(!error)
      {
         //Debug message
         TRACE_INFO("Echo service: %u bytes received from %s port %u\r\n",
            length, ipAddrToString(&ipAddr, NULL), port);

         //Send the data back to the source
         error = socketSendTo(context->socket, &ipAddr, port,
            context->buffer, length, NULL, 0);
      }
   }
}
예제 #2
0
파일: chargen.c 프로젝트: rpc-fw/analyzer
void udpChargenTask(void *param)
{
   error_t error;
   size_t i;
   size_t k;
   size_t n;
   size_t length;
   uint16_t port;
   IpAddr ipAddr;
   ChargenServiceContext *context;

   //Get a pointer to the context
   context = (ChargenServiceContext *) param;

   //Main loop
   while(1)
   {
      //Wait for an incoming datagram
      error = socketReceiveFrom(context->socket, &ipAddr, &port,
         context->buffer, CHARGEN_BUFFER_SIZE, &n, 0);

      //Any datagram received?
      if(!error)
      {
         //When a datagram is received, an answering datagram is sent
         //containing a random number (between 0 and 512) of characters
         length = tcpIpStackGetRand() % 513;

         //Reset line counter
         n = 0;

         //Format output data
         for(i = 0; i < length; i += 74)
         {
            //Calculate the length of the current line
            k = min(length - i, 74);
            //Copy character pattern
            memcpy(context->buffer + i, pattern + n, k);

            //End each line with carriage return and line feed
            if(k == 74)
            {
               context->buffer[i + 72] = '\r';
               context->buffer[i + 73] = '\n';
            }

            //Increment line counter
            if(++n >= 95) n = 0;
         }

         //Send data to the remote host
         error = socketSendTo(context->socket, &ipAddr, port,
            context->buffer, length, &n, 0);

         //Debug message
         TRACE_INFO("Chargen service: %" PRIuSIZE " bytes sent to %s port %" PRIu16 "\r\n",
            n, ipAddrToString(&ipAddr, NULL), port);
      }
   }
}
예제 #3
0
void udpDiscardTask(void *param)
{
   error_t error;
   size_t length;
   uint16_t port;
   IpAddr ipAddr;
   DiscardServiceContext *context;

   //Get a pointer to the context
   context = (DiscardServiceContext *) param;

   //Main loop
   while(1)
   {
      //Wait for an incoming datagram
      error = socketReceiveFrom(context->socket, &ipAddr, &port,
         context->buffer, DISCARD_BUFFER_SIZE, &length, 0);

      //Any datagram received?
      if(!error)
      {
         //Debug message
         TRACE_INFO("Discard service: %" PRIuSIZE " bytes received from %s port %" PRIu16 "\r\n",
            length, ipAddrToString(&ipAddr, NULL), port);

         //Throw away any received datagram...
      }
   }
}
예제 #4
0
int_t recvfrom(int_t s, void *data, int_t size,
   int_t flags, sockaddr *addr, int_t *addrlen)
{
   error_t error;
   size_t received;
   uint16_t port;
   IpAddr ipAddr;
   Socket *socket;

   //Make sure the socket descriptor is valid
   if(s < 0 || s >= SOCKET_MAX_COUNT)
   {
      socketError(NULL, ERROR_INVALID_SOCKET);
      return SOCKET_ERROR;
   }

   //Point to the socket structure
   socket = &socketTable[s];

   //Receive data
   error = socketReceiveFrom(socket, &ipAddr, &port, data, size, &received, flags << 8);

   //Any error to report?
   if(error)
   {
      socketError(socket, error);
      return SOCKET_ERROR;
   }

   //The address is optional
   if(addr != NULL && addrlen != NULL)
   {
#if (IPV4_SUPPORT == ENABLED)
      //IPv4 address?
      if(ipAddr.length == sizeof(Ipv4Addr) && *addrlen >= sizeof(sockaddr_in))
      {
         //Point to the IPv4 address information
         sockaddr_in *sa = (sockaddr_in *) addr;

         //Set address family and port number
         sa->sin_family = AF_INET;
         sa->sin_port = htons(port);
         //Copy IPv4 address
         sa->sin_addr.s_addr = ipAddr.ipv4Addr;

         //Return the actual length of the address
         *addrlen = sizeof(sockaddr_in);
      }
      else
#endif
#if (IPV6_SUPPORT == ENABLED)
      //IPv6 address?
      if(ipAddr.length == sizeof(Ipv6Addr) && *addrlen >= sizeof(sockaddr_in6))
      {
         //Point to the IPv6 address information
         sockaddr_in6 *sa = (sockaddr_in6 *) addr;

         //Set address family and port number
         sa->sin6_family = AF_INET6;
         sa->sin6_port = htons(port);
         //Copy IPv6 address
         ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);

         //Return the actual length of the address
         *addrlen = sizeof(sockaddr_in6);
      }
      else
#endif
      //Invalid address?
      {
         //Report an error
         socketError(socket, ERROR_INVALID_PARAMETER);
         return SOCKET_ERROR;
      }
   }

   //Return the number of bytes received
   return received;
}
예제 #5
0
error_t dhcpv6ForwardRelayReplyMessage(Dhcpv6RelayCtx *context)
{
   error_t error;
   uint_t i;
   uint32_t interfaceId;
   size_t inputMessageLen;
   size_t outputMessageLen;
   Dhcpv6RelayMessage *inputMessage;
   Dhcpv6Message *outputMessage;
   Dhcpv6Option *option;
   IpAddr ipAddr;
   uint16_t port;

   //Point to the buffer where to store the incoming DHCPv6 message
   inputMessage = (Dhcpv6RelayMessage *) context->buffer;

   //Read incoming message
   error = socketReceiveFrom(context->serverSocket, &ipAddr, &port,
      inputMessage, DHCPV6_MAX_MSG_SIZE, &inputMessageLen, 0);
   //Any error to report?
   if(error) return error;

   //Debug message
   TRACE_INFO("\r\nDHCPv6 message received on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
      context->serverInterface->name, inputMessageLen);
   //Dump the contents of the message for debugging purpose
   dhcpv6DumpMessage(inputMessage, inputMessageLen);

   //Check the length of the DHCPv6 message
   if(inputMessageLen < sizeof(Dhcpv6RelayMessage))
      return ERROR_INVALID_MESSAGE;

   //Inspect the message type and only forward Relay-Reply messages.
   //Other DHCPv6 message types must be silently discarded
   if(inputMessage->msgType != DHCPV6_MSG_TYPE_RELAY_REPL)
      return ERROR_INVALID_MESSAGE;

   //Get the length of the Options field
   inputMessageLen -= sizeof(Dhcpv6Message);

   //Check whether an Interface ID option is included in the Relay-Reply
   option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPTION_INTERFACE_ID);
   //Failed to retrieve specified option?
   if(!option || ntohs(option->length) != sizeof(interfaceId))
      return ERROR_INVALID_MESSAGE;

   //Read the Interface ID option contents
   memcpy(&interfaceId, option->value, sizeof(interfaceId));
   //Convert the 32-bit integer from network byte order
   interfaceId = ntohl(interfaceId);

   //The Relay-Reply message must include a Relay Message option
   option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPTION_RELAY_MSG);
   //Failed to retrieve specified option?
   if(!option || ntohs(option->length) < sizeof(Dhcpv6Message))
      return ERROR_INVALID_MESSAGE;

   //Extract the message from the Relay Message option
   outputMessage = (Dhcpv6Message *) option->value;
   //Save the length of the message
   outputMessageLen = ntohs(option->length);

   //Loop through client-facing interfaces
   for(i = 0; i < context->clientInterfaceCount; i++)
   {
      //Check whether the current interface matches the Interface ID option
      if(context->clientInterface[i]->id == interfaceId)
      {
         //Debug message
         TRACE_INFO("Forwarding DHCPv6 message on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
            context->clientInterface[i]->name, outputMessageLen);
         //Dump the contents of the message for debugging purpose
         dhcpv6DumpMessage(outputMessage, outputMessageLen);

         //Copy the peer-address into the destination IP address
         ipAddr.length = sizeof(Ipv6Addr);
         ipAddr.ipv6Addr = inputMessage->peerAddress;

         //Select the relevant port number to use
          if(outputMessage->msgType == DHCPV6_MSG_TYPE_RELAY_REPL)
            port = DHCPV6_SERVER_PORT;
         else
            port = DHCPV6_CLIENT_PORT;

         //Relay the DHCPv6 message to the client on the link
         //identified by the Interface ID option
         return socketSendTo(context->clientSocket[i], &ipAddr,
            port, outputMessage, outputMessageLen, NULL, 0);
      }
   }

   //Unknown interface identifier...
   return ERROR_INVALID_OPTION;
}
예제 #6
0
error_t dhcpv6ForwardClientMessage(Dhcpv6RelayCtx *context, uint_t index)
{
   error_t error;
   uint32_t interfaceId;
   size_t inputMessageLen;
   size_t outputMessageLen;
   Dhcpv6RelayMessage *inputMessage;
   Dhcpv6RelayMessage *outputMessage;
   Dhcpv6Option *option;
   IpAddr ipAddr;

   //Point to the buffer where to store the incoming DHCPv6 message
   inputMessage = (Dhcpv6RelayMessage *) (context->buffer + DHCPV6_RELAY_FORW_OVERHEAD);
   //Message that will be forwarded by the DHCPv6 relay agent
   outputMessage = (Dhcpv6RelayMessage *) context->buffer;

   //Read incoming message
   error = socketReceiveFrom(context->clientSocket[index], &ipAddr, NULL, inputMessage,
      DHCPV6_MAX_MSG_SIZE - DHCPV6_RELAY_FORW_OVERHEAD, &inputMessageLen, 0);
   //Any error to report?
   if(error) return error;

   //Debug message
   TRACE_INFO("\r\nDHCPv6 message received on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
      context->clientInterface[index]->name, inputMessageLen);
   //Dump the contents of the message for debugging purpose
   dhcpv6DumpMessage(inputMessage, inputMessageLen);

   //The source address must be a valid IPv6 address
   if(ipAddr.length != sizeof(Ipv6Addr))
      return ERROR_INVALID_ADDRESS;
   //Check the length of the DHCPv6 message
   if(inputMessageLen < sizeof(Dhcpv6Message))
      return ERROR_INVALID_MESSAGE;

   //When the relay agent receives a valid message to be relayed,
   //it constructs a new Relay-Forward message
   outputMessage->msgType = DHCPV6_MSG_TYPE_RELAY_FORW;

   //Inspect the message type
   switch(inputMessage->msgType)
   {
   //Message received from a client?
   case DHCPV6_MSG_TYPE_SOLICIT:
   case DHCPV6_MSG_TYPE_REQUEST:
   case DHCPV6_MSG_TYPE_CONFIRM:
   case DHCPV6_MSG_TYPE_RENEW:
   case DHCPV6_MSG_TYPE_REBIND:
   case DHCPV6_MSG_TYPE_RELEASE:
   case DHCPV6_MSG_TYPE_DECLINE:
   case DHCPV6_MSG_TYPE_INFO_REQUEST:
      //If the relay agent received the message to be relayed from a client
      //the hop-count in the Relay-Forward message is set to 0
      outputMessage->hopCount = 0;
      //Continue processing
      break;

   //Message received from another relay agent?
   case DHCPV6_MSG_TYPE_RELAY_FORW:
      //If the message received by the relay agent is a Relay-Forward message
      //and the hop-count in the message is greater than or equal to 32, the
      //relay agent discards the received message
      if(inputMessage->hopCount >= DHCPV6_HOP_COUNT_LIMIT)
         return ERROR_INVALID_MESSAGE;
      //Set the hop-count field to the value of the hop-count field in
      //the received message incremented by 1
      outputMessage->hopCount = inputMessage->hopCount + 1;
      //Continue processing
      break;

   //Message received from a server?
   default:
      //Discard ADVERTISE, REPLY, RECONFIGURE and RELAY-REPL messages
      return ERROR_INVALID_MESSAGE;
   }

   //Set the link-address field to the unspecified address
   outputMessage->linkAddress = IPV6_UNSPECIFIED_ADDR;
   //Copy the source address from the header of the IP datagram in
   //which the message was received to the peer-address field
   outputMessage->peerAddress = ipAddr.ipv6Addr;
   //Size of the Relay-Forward message
   outputMessageLen = sizeof(Dhcpv6RelayMessage);

   //Get the interface identifier
   interfaceId = context->clientInterface[index]->id;
   //Convert the 32-bit integer to network byte order
   interfaceId = htonl(interfaceId);
   //If the relay agent cannot use the address in the link-address field
   //to identify the interface through which the response to the client
   //will be relayed, the relay agent must include an Interface ID option
   dhcpv6AddOption(outputMessage, &outputMessageLen,
      DHCPV6_OPTION_INTERFACE_ID, &interfaceId, sizeof(interfaceId));

   //Copy the received DHCPv6 message into a Relay Message option
   option = dhcpv6AddOption(outputMessage, &outputMessageLen,
      DHCPV6_OPTION_RELAY_MSG, NULL, 0);
   //Set the appropriate length of the option
   option->length = htons(inputMessageLen);
   //Adjust the length of the Relay-Forward message
   outputMessageLen += inputMessageLen;

   //Debug message
   TRACE_INFO("Forwarding DHCPv6 message on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
      context->serverInterface->name, outputMessageLen);
   //Dump the contents of the message for debugging purpose
   dhcpv6DumpMessage(outputMessage, outputMessageLen);

   //Destination address to be used when relaying the client message
   ipAddr.length = sizeof(Ipv6Addr);
   ipAddr.ipv6Addr = context->serverAddress;

   //Relay the client message to the server
   return socketSendTo(context->serverSocket, &ipAddr,
      DHCPV6_SERVER_PORT, outputMessage, outputMessageLen, NULL, 0);
}