/************************************************************************ * 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); }
/************************************************************************ * 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); }
/************************************************************************ * 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; }
/************************************************************************ * 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(¶ms->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; }
/************************************************************************ * 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(¶ms->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 *) ¶ms->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 *) ¶ms->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; }
/************************************************************************ * 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); } }
/************************************************************************ * 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); }