Esempio n. 1
0
/************************************************************************
* NAME: fnet_raw_output
*
* DESCRIPTION: RAW output function
*************************************************************************/
static int fnet_raw_output(  struct sockaddr *src_addr, const struct sockaddr *dest_addr, unsigned char protocol_number,
                             fnet_socket_option_t *sockoption, fnet_netbuf_t *nb )                            
{
    int error =  FNET_OK;
    
    fnet_netif_t *netif = FNET_NULL;


#if FNET_CFG_IP4
    if(dest_addr->sa_family == AF_INET)
    {
        error = fnet_ip_output(netif, ((struct sockaddr_in *)(src_addr))->sin_addr.s_addr, 
                                        ((const struct sockaddr_in *)(dest_addr))->sin_addr.s_addr, 
                                        protocol_number, 
                                        sockoption->ip_opt.tos,
                                #if FNET_CFG_MULTICAST
                                    (unsigned char)((FNET_IP4_ADDR_IS_MULTICAST(((const struct sockaddr_in *)(dest_addr))->sin_addr.s_addr)?sockoption->ip_opt.ttl_multicast:sockoption->ip_opt.ttl)),                               
                                #else
                                    sockoption->ip_opt.ttl, 
                                #endif /* FNET_CFG_MULTICAST */                               
                                   nb, 0, ((sockoption->flags & SO_DONTROUTE) > 0),
                                   0
                                   );
    }
#endif
   
#if FNET_CFG_IP6    
    if(dest_addr->sa_family == AF_INET6)
    {
        /* Check Scope ID.*/
        netif = fnet_netif_get_by_scope_id( ((const struct sockaddr_in6 *)dest_addr)->sin6_scope_id );
        
        error = fnet_ip6_output( netif, 
                                fnet_socket_addr_is_unspecified(src_addr)? FNET_NULL : &((struct sockaddr_in6 *)(src_addr))->sin6_addr.s6_addr, 
                                &((const struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr, 
                                protocol_number, 
                                FNET_IP6_ADDR_IS_MULTICAST(&((const struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr)?sockoption->ip6_opt.hops_multicast:sockoption->ip6_opt.hops_unicast,
                                nb,0);
    }
#endif                               

    return (error);
}
Esempio n. 2
0
/************************************************************************
* DESCRIPTION: RAW output function
*************************************************************************/
static fnet_error_t fnet_raw_output(  struct sockaddr *src_addr, const struct sockaddr *dest_addr, fnet_uint8_t protocol_number,
                                      fnet_socket_option_t *sockoption, fnet_netbuf_t *nb )
{
    fnet_error_t error =  FNET_ERR_OK;

    fnet_netif_t *netif =  (fnet_netif_t *)fnet_netif_get_by_scope_id( dest_addr->sa_scope_id );

#if FNET_CFG_IP4
    if(dest_addr->sa_family == AF_INET)
    {
        error = fnet_ip_output(netif, ((struct sockaddr_in *)(src_addr))->sin_addr.s_addr,
                               ((const struct sockaddr_in *)(dest_addr))->sin_addr.s_addr,
                               protocol_number,
                               sockoption->ip_opt.tos,
#if FNET_CFG_MULTICAST
                               (fnet_uint8_t)((FNET_IP4_ADDR_IS_MULTICAST(((const struct sockaddr_in *)(dest_addr))->sin_addr.s_addr) ? sockoption->ip_opt.ttl_multicast : sockoption->ip_opt.ttl)),
#else
                               sockoption->ip_opt.ttl,
#endif /* FNET_CFG_MULTICAST */
                               nb, FNET_FALSE, sockoption->so_dontroute,
                               0
                              );
    }
#endif

#if FNET_CFG_IP6
    if(dest_addr->sa_family == AF_INET6)
    {
        error = fnet_ip6_output( netif,
                                 fnet_socket_addr_is_unspecified(src_addr) ? FNET_NULL : & ((struct sockaddr_in6 *)(src_addr))->sin6_addr.s6_addr,
                                 &((const struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr,
                                 protocol_number,
                                 FNET_IP6_ADDR_IS_MULTICAST(&((const struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr) ? sockoption->ip6_opt.hops_multicast : sockoption->ip6_opt.hops_unicast,
                                 nb, 0);
    }
#endif

    return (error);
}
Esempio n. 3
0
/************************************************************************
* NAME: fnet_raw_input
*
* DESCRIPTION: RAW input function.
*************************************************************************/
void fnet_raw_input(fnet_netif_t *netif, struct sockaddr *foreign_addr,  struct sockaddr *local_addr, fnet_netbuf_t *nb, fnet_netbuf_t *ip_nb)
{
    fnet_socket_t       *sock;
    fnet_socket_t       *last;
    fnet_netbuf_t       *nb_tmp;
    int                 protocol_number;

    if(netif && nb && nb->total_length)
    {
    #if FNET_CFG_IP4
        if(foreign_addr->sa_family == AF_INET)
        {
            protocol_number = ((fnet_ip_header_t *)(ip_nb->data_ptr))->protocol;
        }
        else
    #endif
    #if FNET_CFG_IP6
        if(foreign_addr->sa_family == AF_INET6)
        {
            protocol_number = ((fnet_ip6_header_t *)(ip_nb->data_ptr))->next_header;
        }
        else
    #endif
        {protocol_number = 0;}

        /* Demultiplex broadcast & multicast datagrams.*/
        if(fnet_socket_addr_is_broadcast(local_addr, netif) || fnet_socket_addr_is_multicast(local_addr)) 
        {
            last = 0;

            for (sock = fnet_raw_prot_if.head; sock != 0; sock = sock->next)
            {
                /* Ignore local port number.*/

                /* Check protocol number.*/
                if(sock->protocol_number != protocol_number)
                    continue; /* => ignore.*/
#if FNET_CFG_MULTICAST
                if(fnet_socket_addr_is_multicast(local_addr))
                {
                    int m;
                    int for_us = FNET_FALSE;
                        
                #if FNET_CFG_IP4                        
                    if(local_addr->sa_family == AF_INET)
                    {
                        
                        for(m=0; m < FNET_CFG_MULTICAST_SOCKET_MAX; m++)
                        {
                            if(sock->ip4_multicast_entry[m])
                            {
                                if((sock->ip4_multicast_entry[m]->group_addr == ((struct sockaddr_in *)(local_addr))->sin_addr.s_addr) &&  (sock->ip4_multicast_entry[m]->netif == netif )) 
                                    for_us = FNET_TRUE;       
                            }
                        }
                    }
                #endif    
                #if FNET_CFG_IP6
                    if(local_addr->sa_family == AF_INET6) 
                    {  
                        for(m=0; m < FNET_CFG_MULTICAST_SOCKET_MAX; m++)
                        {
                            if(sock->ip6_multicast_entry[m])
                            {
                                if(FNET_IP6_ADDR_EQUAL(&sock->ip6_multicast_entry[m]->group_addr, &((struct sockaddr_in6 *)(local_addr))->sin6_addr.s6_addr) && (sock->ip6_multicast_entry[m]->netif == netif))
                                    for_us = FNET_TRUE;       
                            }
                        }
                    }
                #endif   
                    
                        
                    if(for_us == FNET_FALSE)
                        continue;
                }
                else
#endif /* FNET_CFG_MULTICAST */                   
                {
                    /* Compare local address.*/
                    if(!fnet_socket_addr_is_unspecified(&sock->local_addr))
                    {
                        if(!fnet_socket_addr_are_equal(&sock->local_addr, local_addr))
                            continue;
                    }

                    /* Compare foreign address and port number.*/
                    if(!fnet_socket_addr_is_unspecified(&sock->foreign_addr))
                    {
                        if((!fnet_socket_addr_are_equal(&sock->foreign_addr, foreign_addr)) ) 
                            continue;
                    }
                    
                }

                if((last != 0) && (last->receive_buffer.is_shutdown == 0))
                {
                    if((nb_tmp = fnet_netbuf_copy(nb, 0, FNET_NETBUF_COPYALL, 0)) != 0)
                    {
                        if(fnet_socket_buffer_append_address(&(last->receive_buffer), nb_tmp, foreign_addr) == FNET_ERR)
                        {
                            fnet_netbuf_free_chain(nb_tmp);
                        }
                    }
                }
                last = sock;
            }

            if(last == 0)
                goto BAD;

            if(last->receive_buffer.is_shutdown) /* Is shutdown.*/
                goto BAD;
                
            /* Copy buffer.*/
            if((nb_tmp = fnet_netbuf_copy(nb, 0, FNET_NETBUF_COPYALL, 0)) != 0)
            {
                if(fnet_socket_buffer_append_address(&(last->receive_buffer), nb_tmp, foreign_addr) == FNET_ERR)
                {
                    fnet_netbuf_free_chain(nb_tmp);
                    goto BAD;
                }
            }
            else
                goto BAD;
        }
        else /* For unicast datagram.*/
        {
            sock = fnet_socket_lookup(fnet_raw_prot_if.head, local_addr, foreign_addr, protocol_number);

            if(sock)
            {
                if(sock->receive_buffer.is_shutdown) /* Is shutdown.*/
                    goto BAD;
                    
                /* Copy buffer.*/
                if((nb_tmp = fnet_netbuf_copy(nb, 0, FNET_NETBUF_COPYALL, 0)) != 0)
                {
                    if(fnet_socket_buffer_append_address(&(sock->receive_buffer), nb_tmp, foreign_addr) == FNET_ERR)
                    {
                        fnet_netbuf_free_chain(nb_tmp);
                        goto BAD;
                    }
                }
                else
                    goto BAD;
            }
        }
    }
BAD:
    return;
}
Esempio n. 4
0
/************************************************************************
* NAME: fnet_dns_init
*
* DESCRIPTION: Initializes DNS client service and starts the host 
*              name resolving.
************************************************************************/
int fnet_dns_init( struct fnet_dns_params *params )
{
    const unsigned long bufsize_option = FNET_DNS_MESSAGE_SIZE;
    unsigned int        total_length;
    unsigned long       host_name_length;
    struct sockaddr     remote_addr;
    fnet_dns_header_t   *header;
  
    /* Check input parameters. */
    if((params == 0) 
        || (params->dns_server_addr.sa_family == AF_UNSPEC) 
        || fnet_socket_addr_is_unspecified(&params->dns_server_addr)
        || (params->handler == 0)
        /* Check length of host_name.*/
        || ((host_name_length = fnet_strlen(params->host_name)) == 0U) || (host_name_length >= FNET_DNS_MAME_SIZE))
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_PARAMS);
        goto ERROR;
    }

    /* Check if DNS service is free.*/
    if(fnet_dns_if.state != FNET_DNS_STATE_DISABLED)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_IS_INITIALIZED);
        goto ERROR;
    }
    
    /* Save input parmeters.*/
    fnet_dns_if.handler = params->handler;
    fnet_dns_if.handler_cookie = params->cookie;
    fnet_dns_if.addr_family = params->addr_family;
    fnet_dns_if.addr_number = 0;

    if(params->addr_family == AF_INET)
    {
        fnet_dns_if.dns_type = FNET_HTONS(FNET_DNS_TYPE_A);
    }
    else
    if(params->addr_family == AF_INET6)
    {
        fnet_dns_if.dns_type = FNET_HTONS(FNET_DNS_TYPE_AAAA);
    }
    else
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_PARAMS);
        goto ERROR;
    }
    
    fnet_dns_if.iteration = 0U;  /* Reset iteration counter.*/
    fnet_dns_if.id++;           /* Change query ID.*/
   
    /* Create socket */
    if((fnet_dns_if.socket_cln = socket(params->dns_server_addr.sa_family, SOCK_DGRAM, 0)) == SOCKET_INVALID)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_SOCKET_CREATION);
        goto ERROR;
    }
    
    /* Set socket options */
    setsockopt(fnet_dns_if.socket_cln, SOL_SOCKET, SO_RCVBUF, (const char *)&bufsize_option, sizeof(bufsize_option));
    setsockopt(fnet_dns_if.socket_cln, SOL_SOCKET, SO_SNDBUF, (const char *)&bufsize_option, sizeof(bufsize_option));
    
    /* Bind/connect to the server.*/
    FNET_DEBUG_DNS("Connecting to DNS Server.");
    fnet_memset_zero(&remote_addr, sizeof(remote_addr));
    remote_addr = params->dns_server_addr;
    if(remote_addr.sa_port == 0U)
    {
        remote_addr.sa_port = FNET_CFG_DNS_PORT;
    }
   
    if(connect(fnet_dns_if.socket_cln, &remote_addr, sizeof(remote_addr))== FNET_ERR)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_SOCKET_CONNECT);
        goto ERROR_1;
    }
    
    /* ==== Build message. ==== */
    fnet_memset_zero(fnet_dns_if.message, sizeof(fnet_dns_if.message)); /* Clear buffer.*/
     
    /* Set header fields:
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    */    
    
    header = (fnet_dns_header_t *)fnet_dns_if.message;
    
    header->id = fnet_dns_if.id;            /* Set ID. */
    
    header->flags = FNET_HTONS(FNET_DNS_HEADER_FLAGS_RD); /* Recursion Desired.*/
   
    header->qdcount = FNET_HTONS(1U);        /* One Question. */
    
    /* No Answer (ANCOUNT).*/ /* No Authority (NSCOUNT). */ /* No Additional (ARCOUNT). */


    total_length = sizeof(fnet_dns_header_t);
    total_length += fnet_dns_add_question( &fnet_dns_if.message[total_length], fnet_dns_if.dns_type, params->host_name);
    fnet_dns_if.message_size = (unsigned long)(total_length);
  
    /* Register DNS service. */
    fnet_dns_if.service_descriptor = fnet_poll_service_register(fnet_dns_state_machine, (void *) &fnet_dns_if);
    if(fnet_dns_if.service_descriptor == (fnet_poll_desc_t)FNET_ERR)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_SERVICE);
        goto ERROR_1;
    }
    
    fnet_dns_if.state = FNET_DNS_STATE_TX; /* => Send request. */    
   
    return FNET_OK;
ERROR_1:
    closesocket(fnet_dns_if.socket_cln);

ERROR:
    return FNET_ERR;
}
Esempio n. 5
0
/************************************************************************
* NAME: fnet_ping_request
*
* DESCRIPTION: Initializes PING service.
************************************************************************/
fnet_return_t fnet_ping_request( struct fnet_ping_params *params )
{
    const fnet_size_t bufsize_option = FNET_PING_BUFFER_SIZE;

    /* Check input parameters. */
    if((params == 0) || (params->packet_count == 0u) || (fnet_socket_addr_is_unspecified(&params->target_addr)))
    {
        FNET_DEBUG_PING(FNET_PING_ERR_PARAMS);
        goto ERROR;
    }

    
    /* Check if PING service is free.*/
    if(fnet_ping_if.state != FNET_PING_STATE_DISABLED)
    {
        FNET_DEBUG_PING(FNET_PING_ERR_IS_INITIALIZED);
        goto ERROR;
    }
    
    /* Save input parmeters.*/
    fnet_ping_if.handler = params->handler;
    fnet_ping_if.handler_cookie = params->cookie;
    fnet_ping_if.timeout_clk = params->timeout/FNET_TIMER_PERIOD_MS;
    if(fnet_ping_if.timeout_clk == 0u)
    {
        fnet_ping_if.timeout_clk = 1u;
    }
    fnet_ping_if.family = params->target_addr.sa_family;
    fnet_ping_if.packet_count = params->packet_count;
    fnet_ping_if.pattern = params->pattern;
    fnet_ping_if.packet_size = params->packet_size;
    if(fnet_ping_if.packet_size > FNET_CFG_PING_PACKET_MAX)
    {
        fnet_ping_if.packet_size = FNET_CFG_PING_PACKET_MAX;
    }
    fnet_ping_if.target_addr  = params->target_addr; 
       
    /* Create socket */
    if((fnet_ping_if.socket_foreign = fnet_socket(fnet_ping_if.family, SOCK_RAW, (fnet_uint32_t)((params->target_addr.sa_family == AF_INET) ? IPPROTO_ICMP : IPPROTO_ICMPV6))) == FNET_ERR)
    {
        FNET_DEBUG_PING(FNET_PING_ERR_SOCKET_CREATION);
        goto ERROR;
    }
    
    /* Set Socket options. */
#if FNET_CFG_IP4    
    if(fnet_ping_if.family == AF_INET) 
    {
        fnet_socket_setopt(fnet_ping_if.socket_foreign, IPPROTO_IP, IP_TTL, (fnet_uint8_t *) &params->ttl, sizeof(params->ttl));
    }
#endif

#if FNET_CFG_IP6        
    if(fnet_ping_if.family == AF_INET6)
    {
        fnet_socket_setopt(fnet_ping_if.socket_foreign, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (fnet_uint8_t *) &params->ttl, sizeof(params->ttl));
    }
#endif        
            
    fnet_socket_setopt(fnet_ping_if.socket_foreign, SOL_SOCKET, SO_RCVBUF, &bufsize_option, sizeof(bufsize_option));
    fnet_socket_setopt(fnet_ping_if.socket_foreign, SOL_SOCKET, SO_SNDBUF, &bufsize_option, sizeof(bufsize_option));

    /* Register PING service. */
    fnet_ping_if.service_descriptor = fnet_poll_service_register(fnet_ping_state_machine, (void *) &fnet_ping_if);
    if(fnet_ping_if.service_descriptor == (fnet_poll_desc_t)FNET_ERR)
    {
        FNET_DEBUG_PING(FNET_PING_ERR_SERVICE);
        goto ERROR_1;
    }
    
    fnet_ping_if.state = FNET_PING_STATE_SENDING_REQUEST;
    
    return FNET_OK;
    
ERROR_1:
    fnet_socket_close(fnet_ping_if.socket_foreign);

ERROR:
    return FNET_ERR;
}
Esempio n. 6
0
/************************************************************************
* NAME: fnet_udp_input
*
* DESCRIPTION: UDP input function.
*************************************************************************/
static void fnet_udp_input(fnet_netif_t *netif, struct sockaddr *foreign_addr,  struct sockaddr *local_addr, fnet_netbuf_t *nb, fnet_netbuf_t *ip_nb)
{
    fnet_udp_header_t   *udp_header = (fnet_udp_header_t *)nb->data_ptr;
    fnet_socket_if_t       *sock;
    fnet_socket_if_t       *last;
    fnet_size_t         udp_length;
    fnet_netbuf_t       *nb_tmp;

    if((netif != 0) && (nb != 0))
    {
        /* The header must reside in contiguous area of memory.*/
        if(fnet_netbuf_pullup(&nb, sizeof(fnet_udp_header_t)) == FNET_ERR) 
        {
            goto BAD;
        }
        
        udp_length = fnet_ntohs(udp_header->length);

        if(nb->total_length >= udp_length)  /* Check the amount of data.*/
        {
            if(nb->total_length > udp_length)
            {
                /* Logical size and the physical size of the packet should be the same.*/
                fnet_netbuf_trim(&nb, (fnet_int32_t)(udp_length - nb->total_length)); 
            }

#if FNET_CFG_UDP_CHECKSUM
            if((udp_header->checksum != 0u)
        #if FNET_CFG_CPU_ETH_HW_RX_PROTOCOL_CHECKSUM || FNET_CFG_CPU_ETH_HW_TX_PROTOCOL_CHECKSUM
            && ((nb->flags & FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM) == 0)
        #endif
            )
            {
                fnet_uint16_t sum;
                
                sum = fnet_checksum_pseudo_start( nb, FNET_HTONS((fnet_uint16_t)FNET_IP_PROTOCOL_UDP), (fnet_uint16_t)udp_length );
                sum = fnet_checksum_pseudo_end( sum, &foreign_addr->sa_data[0], &local_addr->sa_data[0], 
                            (fnet_size_t)((local_addr->sa_family == AF_INET) ? sizeof(fnet_ip4_addr_t) : sizeof(fnet_ip6_addr_t)));

                if(sum)
                {
                    goto BAD;
                }
            }
#endif
            fnet_udp_trace("RX", udp_header); /* Trace UDP header.*/

            local_addr->sa_port = udp_header->destination_port;
            foreign_addr->sa_port = udp_header->source_port;

            fnet_netbuf_trim(&nb, (fnet_int32_t)sizeof(fnet_udp_header_t));

            /* Demultiplex broadcast & multicast datagrams.*/
            if((fnet_socket_addr_is_broadcast(local_addr, netif)) || (fnet_socket_addr_is_multicast(local_addr))) 
            {
                last = 0;

                for (sock = fnet_udp_prot_if.head; sock != 0; sock = sock->next)
                {
                    /* Compare local port number.*/
                    if(sock->local_addr.sa_port != local_addr->sa_port)
                    {
                        continue; /* => ignore.*/
                    }

                #if FNET_CFG_MULTICAST
                    if(fnet_socket_addr_is_multicast(local_addr)) 
                    {
                        fnet_index_t        m;
                        fnet_bool_t         for_us = FNET_FALSE;
                        
                    #if FNET_CFG_IP4                        
                        if(local_addr->sa_family == AF_INET)
                        {
                            for(m = 0u; m < FNET_CFG_MULTICAST_SOCKET_MAX; m++)
                            {
                                if(sock->ip4_multicast_entry[m])
                                {
                                    if((sock->ip4_multicast_entry[m]->group_addr == ((struct sockaddr_in *)(local_addr))->sin_addr.s_addr) &&  (sock->ip4_multicast_entry[m]->netif == netif )) 
                                    {
                                        for_us = FNET_TRUE;       
                                    }
                                }
                            }
                        }
                        else
                     #endif    
                     #if FNET_CFG_IP6
                        if(local_addr->sa_family == AF_INET6) 
                        {  
                            for(m=0u; m < FNET_CFG_MULTICAST_SOCKET_MAX; m++)
                            {
                                if(sock->ip6_multicast_entry[m])
                                {
                                   
                                    if(FNET_IP6_ADDR_EQUAL(&sock->ip6_multicast_entry[m]->group_addr, &((struct sockaddr_in6 *)(local_addr))->sin6_addr.s6_addr) && (sock->ip6_multicast_entry[m]->netif == netif))
                                    {
                                        for_us = FNET_TRUE;       
                                    }
                                }
                            }
                        }
                        else
                     #endif   
                        {}

                        if(for_us == FNET_FALSE)
                        {
                            continue;
                        }
                    }
                    else
                #endif /* FNET_CFG_MULTICAST */                   
                    {
                        /* Compare local address.*/
                        if(!fnet_socket_addr_is_unspecified(&sock->local_addr))
                        {
                            if(!fnet_socket_addr_are_equal(&sock->local_addr, local_addr))
                            {
                                continue;
                            }    
                        }

                        /* Compare foreign address and port number.*/
                        if(!fnet_socket_addr_is_unspecified(&sock->foreign_addr))
                        {
                            if((!fnet_socket_addr_are_equal(&sock->foreign_addr, foreign_addr)) || (sock->foreign_addr.sa_port != foreign_addr->sa_port))
                            {
                                continue;
                            }
                        }
                    }

                    if((last != 0) && (last->receive_buffer.is_shutdown == FNET_FALSE))
                    {
                        if((nb_tmp = fnet_netbuf_copy(nb, 0u, FNET_NETBUF_COPYALL, FNET_FALSE)) != 0)
                        {
                            if(fnet_socket_buffer_append_address(&(last->receive_buffer), nb_tmp, foreign_addr) == FNET_ERR)
                            {
                                fnet_netbuf_free_chain(nb_tmp);
                            }
                        }
                    }
                    last = sock;
                }

                if(last == 0)
                {
                    goto BAD;
                }

                if(last->receive_buffer.is_shutdown) /* Is shutdown.*/
                {
                    goto BAD;
                }

                if(fnet_socket_buffer_append_address(&(last->receive_buffer), nb, foreign_addr) == FNET_ERR)
                {
                    goto BAD;
                }
                
                fnet_netbuf_free_chain(ip_nb);                  
            }
            else /* For unicast datagram.*/
            {
                sock = fnet_socket_lookup(fnet_udp_prot_if.head, local_addr, foreign_addr, FNET_IP_PROTOCOL_UDP);

                if(sock)
                {
                    if(sock->receive_buffer.is_shutdown) /* Is shutdown.*/
                    {
                        goto BAD;
                    }
                    if(fnet_socket_buffer_append_address(&(sock->receive_buffer), nb, foreign_addr) == FNET_ERR)
                    {
                        goto BAD;
                    }
                    
                    fnet_netbuf_free_chain(ip_nb);
                }
                else
                {
                    fnet_netbuf_free_chain(nb); /* No match was found, send ICMP destination port unreachable.*/
                #if FNET_CFG_IP4                    
                    if(local_addr->sa_family == AF_INET)
                    {
                        fnet_icmp_error(netif, FNET_ICMP_UNREACHABLE, FNET_ICMP_UNREACHABLE_PORT, ip_nb);
                    }else
                #endif
                #if FNET_CFG_IP6                        
                    if(local_addr->sa_family == AF_INET6)
                    {
                        fnet_icmp6_error(netif, FNET_ICMP6_TYPE_DEST_UNREACH, FNET_ICMP6_CODE_DU_PORT_UNREACH, 0u, ip_nb );
                    }else
                #endif
                    {}                
                }
            }
        }
        else
        {
            goto BAD;
        }
    }
    else
    {
BAD:
        fnet_netbuf_free_chain(ip_nb);
        fnet_netbuf_free_chain(nb);
    }
}
Esempio n. 7
0
/************************************************************************
* NAME: fnet_udp_output
*
* DESCRIPTION: UDP output function
*************************************************************************/
static fnet_error_t fnet_udp_output(  struct sockaddr *src_addr, const struct sockaddr *dest_addr,
                             fnet_socket_option_t *sockoption, fnet_netbuf_t *nb )                            
{
    fnet_netbuf_t                           *nb_header;
    fnet_udp_header_t                       *udp_header;
    fnet_error_t                            error =  FNET_ERR_OK;
    FNET_COMP_PACKED_VAR fnet_uint16_t      *checksum_p;
    fnet_netif_t                            *netif = FNET_NULL;
    fnet_scope_id_t                         scope_id = 0u;

    /* Check Scope ID.*/
    if(dest_addr->sa_scope_id) /* Take scope id from destination address.*/
    {
        scope_id = dest_addr->sa_scope_id;
    }
    else  /* Take scope id from source address.*/
    {
        scope_id = src_addr->sa_scope_id;
    }
    netif = (fnet_netif_t *)fnet_netif_get_by_scope_id(scope_id); /* It can be FNET_NULL, in case scope_id is 0.*/

    /* Construct UDP header.*/
    if((nb_header = fnet_netbuf_new(sizeof(fnet_udp_header_t), FNET_TRUE)) == 0)
    {
        fnet_netbuf_free_chain(nb); 
        return (FNET_ERR_NOMEM);
    }

    udp_header = (fnet_udp_header_t *)nb_header->data_ptr;

    udp_header->source_port = src_addr->sa_port;             /* Source port number.*/
    udp_header->destination_port = dest_addr->sa_port;       /* Destination port number.*/
    nb = fnet_netbuf_concat(nb_header, nb);
    udp_header->length = fnet_htons((fnet_uint16_t)nb->total_length);  /* Length.*/

    /* Checksum calculation.*/
    udp_header->checksum = 0u;  

#if FNET_CFG_UDP_CHECKSUM

#if FNET_CFG_CPU_ETH_HW_TX_IP_CHECKSUM
    if( 0 
    #if FNET_CFG_IP4
        ||( (dest_addr->sa_family == AF_INET) 
        && ((netif = fnet_ip_route(((struct sockaddr_in *)(dest_addr))->sin_addr.s_addr))!= FNET_NULL)
        && (netif->features & FNET_NETIF_FEATURE_HW_TX_PROTOCOL_CHECKSUM)
        && (fnet_ip_will_fragment(netif, nb->total_length) == FNET_FALSE) /* Fragmented packets are not inspected.*/  ) 
    #endif
    #if FNET_CFG_IP6
        ||( (dest_addr->sa_family == AF_INET6) 
        && (netif || (((netif = fnet_ip6_route(&((struct sockaddr_in6 *)(src_addr))->sin6_addr.s6_addr, &((struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr)))!= FNET_NULL) )
        && (netif->features & FNET_NETIF_FEATURE_HW_TX_PROTOCOL_CHECKSUM)
        && (fnet_ip6_will_fragment(netif, nb->total_length) == FNET_FALSE) /* Fragmented packets are not inspected.*/  ) 
    #endif
    )
    {
        nb->flags |= FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM;
        checksum_p = 0;
    }
    else
#endif /* FNET_CFG_CPU_ETH_HW_TX_IP_CHECKSUM */
    {
        udp_header->checksum = fnet_checksum_pseudo_start( nb, FNET_HTONS((fnet_uint16_t)FNET_IP_PROTOCOL_UDP), (fnet_uint16_t)nb->total_length );
        checksum_p = &udp_header->checksum;
    }
#endif /* FNET_CFG_UDP_CHECKSUM */

#if FNET_CFG_IP4
    if(dest_addr->sa_family == AF_INET)
    {
        error = fnet_ip_output(netif, 
                                ((const struct sockaddr_in *)(src_addr))->sin_addr.s_addr, 
                                ((const struct sockaddr_in *)(dest_addr))->sin_addr.s_addr, 
                                FNET_IP_PROTOCOL_UDP, sockoption->ip_opt.tos,
                            #if FNET_CFG_MULTICAST
                                (fnet_uint8_t)((FNET_IP4_ADDR_IS_MULTICAST(((const struct sockaddr_in *)(dest_addr))->sin_addr.s_addr)?sockoption->ip_opt.ttl_multicast:sockoption->ip_opt.ttl)),                               
                            #else
                                sockoption->ip_opt.ttl, 
                            #endif /* FNET_CFG_MULTICAST */                               
                                nb, FNET_UDP_DF, sockoption->so_dontroute,
                                checksum_p
                                );
    }
    else
#endif
#if FNET_CFG_IP6    
    if(dest_addr->sa_family == AF_INET6)
    {
        error = fnet_ip6_output( netif, 
                                fnet_socket_addr_is_unspecified(src_addr)? FNET_NULL : &((struct sockaddr_in6 *)(src_addr))->sin6_addr.s6_addr, 
                                &((const struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr, 
                                FNET_IP_PROTOCOL_UDP, 
                                FNET_IP6_ADDR_IS_MULTICAST(&((const struct sockaddr_in6 *)(dest_addr))->sin6_addr.s6_addr)?sockoption->ip6_opt.hops_multicast:sockoption->ip6_opt.hops_unicast,
                                nb, 
                                checksum_p
                                );
    }
    else
#endif                               
    {}

    return (error);
}