Exemplo n.º 1
0
STATUS NU_Bootp ( CHAR  *dv_name, BOOTP_STRUCT *bp_ptr)
{
    uint16              delay, delay_mask = 3;
    int                 i;
    int                 ret;
    BOOTPLAYER          *bootp_ptr;
    IPLAYER             *ip_ptr;
    UDPLAYER            *udp_pkt;
    NET_BUFFER          *buf_ptr;
    NET_BUFFER          *next_buf=0;
    struct pseudotcp    tcp_chk;
    int16               failed = 0,retval=0;
    DV_DEVICE_ENTRY     *int_face=0;
    int16               socketd;
    uint8               *buffer;
    struct addr_struct  clientaddr;
    uint16              nbytes;
    STATUS              status;
    int16               hlen = sizeof (IPLAYER);
    INT                 length;
    int32               total_size, current_size;
    int                 found = 0;    
    int32               flags;
    SCK_SOCKADDR        sa;
    int32               temp_data_len,temp_total_data_len;
    DLAYER              *ether_header;

	/* Create a socket and bind to it, so that we can receive packets. */
    socketd = NU_Socket(NU_FAMILY_IP, NU_TYPE_DGRAM, NU_NONE);
    if( socketd < 0 )
    {
        NU_Tcp_Log_Error( BOOTP_SOCKET, TCP_FATAL, __FILE__, __LINE__);
        return (NU_BOOTP_INIT_FAILED);
    }

    /* build local address and port to bind to. */
    clientaddr.family = NU_FAMILY_IP;
    clientaddr.port   = IPPORT_BOOTPC;
    clientaddr.id.is_ip_addrs[0] = (uint8) 0;
    clientaddr.id.is_ip_addrs[1] = (uint8) 0;
    clientaddr.id.is_ip_addrs[2] = (uint8) 0;
    clientaddr.id.is_ip_addrs[3] = (uint8) 0;
    clientaddr.name = "ATI";

    /*  Allocate memory for the buffer space */
    status = NU_Allocate_Memory(&System_Memory,(VOID **) &buffer,sizeof(BOOTPLAYER), NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
            return (NU_BOOTP_INIT_FAILED);


    ret = NU_Bind(socketd, &clientaddr, 0);
    if( ret != socketd )
    {
        NU_Tcp_Log_Error( BOOTP_SOCKET_BIND, TCP_FATAL,
                    __FILE__, __LINE__);
        NU_Close_Socket(socketd);
        return (NU_BOOTP_INIT_FAILED);
    }

    UTL_Zero(bp_ptr->bp_mac_addr, sizeof(bp_ptr->bp_mac_addr));
    UTL_Zero(bp_ptr->bp_siaddr,sizeof(bp_ptr->bp_siaddr));
    UTL_Zero(bp_ptr->bp_giaddr,sizeof(bp_ptr->bp_giaddr));
    UTL_Zero(bp_ptr->bp_sname,sizeof(bp_ptr->bp_sname));
    UTL_Zero(bp_ptr->bp_file,sizeof(bp_ptr->bp_file));
	
    /*  Get the device by name to be used on BOOTP for this iteration. */
 
    int_face = DEV_Get_Dev_By_Name(dv_name);

    if (int_face->dev_mtu < BOOTP_MAX_HEADER_SIZE)
        return (NU_BOOTP_INIT_FAILED);

    /* copy the hardware address from the device structure */
    memcpy(bp_ptr->bp_mac_addr, int_face->dev_mac_addr, DADDLEN);

    /*  make sure that the MAC address is a good.  */
    if ( memcmp(bp_ptr->bp_mac_addr, "\0\0\0\0\0\0", 6) == 0)
        return (NU_BOOTP_INIT_FAILED);

    buf_ptr = MEM_Buffer_Chain_Dequeue(&MEM_Buffer_Freelist, BOOTP_MAX_HEADER_SIZE);

    if (buf_ptr == NU_NULL)
        return (NU_NO_BUFFERS);

    buf_ptr->mem_dlist = &BOOTP_List;


    UTL_Zero(buf_ptr->mem_parent_packet, sizeof(NET_PARENT_BUFFER_SIZE));
    
    
    if (buf_ptr->next_buffer != NU_NULL)
    {
        next_buf= buf_ptr->next_buffer;
    }
    
     UTL_Zero(next_buf->mem_packet, sizeof(NET_MAX_BUFFER_SIZE));





    /* Set up pointers to each of the headers that make up a BOOTP Packet.  */
    bootp_ptr = (BOOTPLAYER *)(buf_ptr->mem_parent_packet + (BOOTP_MAX_HEADER_SIZE - (sizeof(BOOTPLAYER))));
    udp_pkt  = (UDPLAYER *) (((char *)bootp_ptr) - sizeof(UDPLAYER));
    ip_ptr   = (IPLAYER *) (((char *)udp_pkt) - sizeof(IPLAYER));

    /*  Build the BOOTP Request Packet  */

    nbytes = BOOTP_init((BOOTPLAYER *)buffer, bp_ptr);

    /*  Initialize the local and foreign port numbers  */

    udp_pkt->source = intswap(IPPORT_BOOTPC);
    udp_pkt->dest   = intswap(IPPORT_BOOTPS);

    /* Set up the UDP Header  */

    udp_pkt->length = intswap ((uint16) (nbytes + sizeof(UDPLAYER)));

    udp_pkt->check = 0;



    buf_ptr->data_ptr = buf_ptr->mem_parent_packet + NET_MAX_UDP_HEADER_SIZE;
    total_size = nbytes;

    /*  Chain the Bootp Request Packet */

    if (total_size > NET_PARENT_BUFFER_SIZE)
    {
       current_size = NET_PARENT_BUFFER_SIZE - sizeof(IPLAYER) - NET_ETHER_HEADER_OFFSET_SIZE;
       total_size =   total_size - current_size;
    }
    else
    {
       current_size =  total_size;
    }

    /*  Copy Bootp Packet into first Buffer */
    memcpy(buf_ptr->data_ptr , buffer, current_size);

    /*  Set the Data Length to the Size of bytes copied.  */
    buf_ptr->data_len = current_size;

    /*  Set the Total data length to the Number of bytes in a Bootp Packet. */
    buf_ptr->mem_total_data_len = nbytes;

    /*  Increment Bootp Buffer to be at the number of bytes copied.  */
    buffer = buffer + current_size;

    /*  Check to make sure there is data to store in the mem_packet */

    while ((total_size) && (next_buf != NU_NULL))
    {

         if (total_size > NET_MAX_BUFFER_SIZE)
         {
             
             current_size = NET_MAX_BUFFER_SIZE;
         }
         else
         {
             current_size = total_size;
         }
         total_size = total_size - current_size;

         /*  Copy the remaining data in the chaining packets  */
         memcpy(next_buf->mem_packet,buffer,current_size);

         /*  Set the Data pointer to the remainder of the packets.  */
         next_buf->data_ptr = next_buf->mem_packet;
         next_buf->next = NU_NULL;
         next_buf->data_len = current_size;


         buffer = buffer + current_size;

         if (next_buf->next_buffer != NU_NULL)
         {
            next_buf = next_buf->next_buffer;
         }

    }

    /* Increment the Packet data pointer to the UDP layer */
    buf_ptr->data_ptr -= sizeof(UDPLAYER);

    /*  Copy the udp_pkt into the parent_packet.  */
    memcpy(buf_ptr->data_ptr,(uint8 *)udp_pkt,sizeof(UDPLAYER));

    /*  Increment the total data length */
    buf_ptr->mem_total_data_len += sizeof(UDPLAYER);

    /*  Increment the data length of this packet.  */
    buf_ptr->data_len += sizeof(UDPLAYER);

    /*  Calculate UDP Checksum  */

    tcp_chk.source  = 0x0;
    tcp_chk.dest    = 0xFFFFFFFF;
    tcp_chk.z       = 0;
    tcp_chk.proto   = IP_UDP_PROT;
    tcp_chk.tcplen  = intswap((uint16)buf_ptr->mem_total_data_len);
    udp_pkt->check =  tcpcheck( (uint16 *)&tcp_chk, buf_ptr);

    /* If a checksum of zero is computed it should be replaced with 0xffff. */
    if (udp_pkt->check == 0)
        udp_pkt->check = 0xFFFF;


   /*  Set up the IP header  */
    ip_ptr->versionandhdrlen = (((hlen >> 2)) | (IP_VERSION << 4));

    /*  Set the IP header to no fragments. */

    ip_ptr->frags = 0;

    /* Set the IP packet ID.  */

    ip_ptr->ident = 0;

    /* Set the type of service. */

    ip_ptr->service = 0;

    length = nbytes +(uint16)sizeof(UDPLAYER);

    /* Set the total length( data and IP header) for this packet. */

    ip_ptr->tlen = intswap((int16)(length + hlen));

    /*  Set the time to live. */

    ip_ptr->ttl = IP_TIME_TO_LIVE;

    /*  Set the protocol. */

    ip_ptr->protocol = IP_UDP_PROT;


    /* We are doing a broadcast, so we do not need this fields. */

    memset(ip_ptr->ipsource,0,4);
    memcpy(ip_ptr->ipdest,"\377\377\377\377",4);


    /*  Compute the IP checksum. */
    ip_ptr->check = 0;
    ip_ptr->check = ipcheck((uint16 *)ip_ptr, (uint16)(hlen >> 1));

    /*  Set the buffer pointer to the IP Layer.  */

    buf_ptr->data_ptr -= sizeof(IPLAYER);

    /*  Add the IPLAYER to the total data length */

    buf_ptr->mem_total_data_len += sizeof(IPLAYER);
    temp_total_data_len =  buf_ptr->mem_total_data_len;

    /*  Set the data length of the current packet.  */

    buf_ptr->data_len += sizeof(IPLAYER);
    temp_data_len =  buf_ptr->data_len;

    /*  Copy the IP header into the parent packet of the buffer chain.  */

    memcpy(buf_ptr->data_ptr,(uint8 *)ip_ptr,sizeof(IPLAYER));

    /*  Set initial Delay for Processing packets.  */

    delay= (delay_mask & NU_rand()) + 1;

    /*  Innitialize the ethernet header.  */

    ether_header = (DLAYER *)sa.sck_data;
    memcpy(ether_header->dest, NET_Ether_Broadaddr, DADDLEN);
    memcpy(ether_header->me, bp_ptr->bp_mac_addr, DADDLEN);
    ether_header->type = EIP;

    sa.sck_family = SK_FAM_UNSPEC;
    sa.sck_len = sizeof(sa);

    /*  Transmit the packet  */

    for(i=0; i< BOOTP_RETRIES; i++)
    {
        
        /* Grab the semaphore because we are about to change the interface
           that the BOOTP request will be sent over. */
        NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);

        /* The device will not send packets until an IP address is attached.
           Temporarily trick it into thinking an IP address is attached so this
           request can be sent.  Then set it back. */
        flags = int_face->dev_flags;
        int_face->dev_flags |= (DV_UP | DV_RUNNING);

        /* Send the packet. */
        status = (*(int_face->dev_output)) (buf_ptr, int_face,
                                            (SCK_SOCKADDR_IP *)&sa, NU_NULL);
        int_face->dev_flags = flags;

        NU_Release_Semaphore(&TCP_Resource);

        if( status != NU_SUCCESS)
        {
            NU_Tcp_Log_Error(BOOTP_SEND_FAILED, TCP_FATAL, __FILE__,__LINE__);
            break;
        }

        /*  Look at each packet on the buffer list to see if it is my reply */
        found = BOOTP_Process_Packets(socketd, bp_ptr, delay);

        if (found)
            break;                           /*  Found the Packet. */

        delay_mask++;


        delay = (delay_mask & NU_rand()) + 1;

        /*  Get the the packet off the Trasmitted list and retrasnmit again. */
        buf_ptr= BOOTP_List.head;
        buf_ptr->data_ptr = BOOTP_List.head->mem_parent_packet + NET_ETHER_HEADER_OFFSET_SIZE;
        buf_ptr->data_len = temp_data_len;
        buf_ptr->mem_total_data_len = temp_total_data_len;
    }  /*  End For Loop */


    if( found == 1 )
    {
        status = DEV_Attach_IP_To_Device( dv_name, bp_ptr->bp_yiaddr,
                                          bp_ptr->bp_net_mask);
        if( status != NU_SUCCESS )
        {
            NU_Tcp_Log_Error( BOOTP_ATTACH_IP, TCP_FATAL,
                  __FILE__, __LINE__);
            failed++;
        }

    }
	
    retval= failed + retval;
	   
    /* Cleanup */
    NU_Close_Socket(socketd);

    /*  Free the Buffer Chain.  */
    MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
    NU_Deallocate_Memory(buffer);
    if(!found)
        retval= BOOTP_RECV_FAILED;
    
    return(retval);
    
}  /* NU_Bootp */
Exemplo n.º 2
0
static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
{
    STATUS status;
    struct addr_struct servaddr;
    NU_HOSTENT *hentry;
    INT family;
    CHAR test_ip[MAX_ADDRESS_SIZE] = {0};

    XMEMSET(&servaddr, 0, sizeof(struct addr_struct));

    /* Determine the IP address of the foreign server to which to
     * make the connection.
     */
#if (INCLUDE_IPV6 == NU_TRUE)
    /* Search for a ':' to determine if the address is IPv4 or IPv6. */
    if (XMEMCHR(ip, (int)':', MAX_ADDRESS_SIZE) != NU_NULL) {
        family = NU_FAMILY_IP6;
    }
    else
#endif
    {
#if (INCLUDE_IPV4 == NU_FALSE)
        /* An IPv6 address was not passed into the routine. */
        return -1;
#else
        family = NU_FAMILY_IP;
#endif
    }

    /* Convert the string to an array. */
    status = NU_Inet_PTON(family, (char*)ip, test_ip);

    /* If the URI contains an IP address, copy it into the server structure. */
    if (status == NU_SUCCESS) {
        XMEMCPY(servaddr.id.is_ip_addrs, test_ip, MAX_ADDRESS_SIZE);
    }

    /* If the application did not pass in an IP address, resolve the host
     * name into a valid IP address.
     */
    else {
        /* If IPv6 is enabled, default to IPv6.  If the host does not have
         * an IPv6 address, an IPv4-mapped IPv6 address will be returned that
         * can be used as an IPv6 address.
         */
#if (INCLUDE_IPV6 == NU_TRUE)
        family = NU_FAMILY_IP6;
#else
        family = NU_FAMILY_IP;
#endif

        /* Try getting host info by name */
        hentry = NU_Get_IP_Node_By_Name((char*)ip, family, DNS_V4MAPPED, &status);
        if (hentry) {
            /* Copy the hentry data into the server structure */
            XMEMCPY(servaddr.id.is_ip_addrs, *hentry->h_addr_list, hentry->h_length);
            family = hentry->h_addrtype;

            /* Free the memory associated with the host entry returned */
            NU_Free_Host_Entry(hentry);
        }

        /* If the host name could not be resolved, return an error. */
        else {
            return -1;
        }
    }

    /* Set the family field. */
    servaddr.family = family;

    /* Set the port field. */
    servaddr.port = port;

    status = NU_Socket(family, NU_TYPE_STREAM, NU_NONE);
    if (status >= 0) {
        /* Assign socket */
        *sockfd = status;
    }
    else {
        WOLFSSL_MSG("bad socket fd, out of fds?");
        return(-1);
    }

    status = NU_Connect((INT)*sockfd, &servaddr, 0);
    if (status != *sockfd) {
        WOLFSSL_MSG("OCSP responder tcp connect failed");
        return -1;
    }

    return 0;
}