int tcp_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr_in *addr) #endif { net_lock_t flags; int port; /* Verify or select a local port */ flags = net_lock(); port = tcp_selectport(ntohs(addr->sin_port)); net_unlock(flags); if (port < 0) { return port; } /* Save the local address in the connection structure. Note that the requested * local IP address is saved but not used. At present, only a single network * interface is supported, the IP address is not of importance. */ conn->lport = addr->sin_port; #if 0 /* Not used */ #ifdef CONFIG_NET_IPv6 net_ipaddr_copy(conn->lipaddr, addr->sin6_addr.in6_u.u6_addr16); #else net_ipaddr_copy(conn->lipaddr, addr->sin_addr.s_addr); #endif #endif return OK; }
int udp_connect(FAR struct udp_conn_s *conn, FAR const struct sockaddr_in *addr) #endif { /* Has this address already been bound to a local port (lport)? */ if (!conn->lport) { /* No.. Find an unused local port number and bind it to the * connection structure. */ conn->lport = htons(udp_select_port()); } /* Is there a remote port (rport) */ if (addr) { conn->rport = addr->sin_port; net_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr); } else { conn->rport = 0; net_ipaddr_copy(conn->ripaddr, g_allzeroaddr); } conn->ttl = IP_TTL; return OK; }
static int get_local_addr(struct http_client_ctx *ctx) { if (ctx->tcp.local.family == AF_INET6) { #if defined(CONFIG_NET_IPV6) struct in6_addr *dst = &net_sin6(&ctx->tcp.remote)->sin6_addr; net_ipaddr_copy(&net_sin6(&ctx->tcp.local)->sin6_addr, net_if_ipv6_select_src_addr(NULL, dst)); #else return -EPFNOSUPPORT; #endif } else if (ctx->tcp.local.family == AF_INET) { #if defined(CONFIG_NET_IPV4) struct net_if *iface = net_if_get_default(); /* For IPv4 we take the first address in the interface */ net_ipaddr_copy(&net_sin(&ctx->tcp.local)->sin_addr, &iface->ipv4.unicast[0].address.in_addr); #else return -EPFNOSUPPORT; #endif } return 0; }
static void dns_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data) { struct waiter *waiter = user_data; struct http_client_ctx *ctx = waiter->ctx; if (!(status == DNS_EAI_INPROGRESS && info)) { return; } if (info->ai_family == AF_INET) { #if defined(CONFIG_NET_IPV4) net_ipaddr_copy(&net_sin(&ctx->tcp.remote)->sin_addr, &net_sin(&info->ai_addr)->sin_addr); #else goto out; #endif } else if (info->ai_family == AF_INET6) { #if defined(CONFIG_NET_IPV6) net_ipaddr_copy(&net_sin6(&ctx->tcp.remote)->sin6_addr, &net_sin6(&info->ai_addr)->sin6_addr); #else goto out; #endif } else { goto out; } ctx->tcp.remote.family = info->ai_family; out: k_sem_give(&waiter->wait); }
static void setup_ipv4_udp(struct net_pkt *pkt, struct in_addr *remote_addr, struct in_addr *local_addr, u16_t remote_port, u16_t local_port) { NET_IPV4_HDR(pkt)->vhl = 0x45; NET_IPV4_HDR(pkt)->tos = 0; NET_IPV4_HDR(pkt)->len[0] = 0; NET_IPV4_HDR(pkt)->len[1] = NET_UDPH_LEN + sizeof(struct net_ipv4_hdr) + strlen(payload); NET_IPV4_HDR(pkt)->proto = IPPROTO_UDP; net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src, remote_addr); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, local_addr); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr)); net_pkt_set_ipv6_ext_len(pkt, 0); net_buf_add(pkt->frags, net_pkt_ip_hdr_len(pkt) + sizeof(struct net_udp_hdr)); NET_UDP_HDR(pkt)->src_port = htons(remote_port); NET_UDP_HDR(pkt)->dst_port = htons(local_port); net_buf_add_mem(pkt->frags, payload, strlen(payload)); }
static void setup_ipv6_udp(struct net_pkt *pkt, struct in6_addr *remote_addr, struct in6_addr *local_addr, u16_t remote_port, u16_t local_port) { NET_IPV6_HDR(pkt)->vtc = 0x60; NET_IPV6_HDR(pkt)->tcflow = 0; NET_IPV6_HDR(pkt)->flow = 0; NET_IPV6_HDR(pkt)->len[0] = 0; NET_IPV6_HDR(pkt)->len[1] = NET_UDPH_LEN + strlen(payload); NET_IPV6_HDR(pkt)->nexthdr = IPPROTO_UDP; NET_IPV6_HDR(pkt)->hop_limit = 255; net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src, remote_addr); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, local_addr); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); net_pkt_set_ipv6_ext_len(pkt, 0); net_buf_add(pkt->frags, net_pkt_ip_hdr_len(pkt) + sizeof(struct net_udp_hdr)); NET_UDP_HDR(pkt)->src_port = htons(remote_port); NET_UDP_HDR(pkt)->dst_port = htons(local_port); net_buf_add_mem(pkt->frags, payload, strlen(payload)); }
int net_addroute(net_ipaddr_t target, net_ipaddr_t netmask, net_ipaddr_t router) { FAR struct net_route_s *route; net_lock_t save; /* Allocate a route entry */ route = net_allocroute(); if (!route) { ndbg("ERROR: Failed to allocate a route\n"); return -ENOMEM; } /* Format the new route table entry */ net_ipaddr_copy(route->target, target); net_ipaddr_copy(route->netmask, netmask); net_ipaddr_copy(route->router, router); /* Get exclusive address to the networking data structures */ save = net_lock(); /* Then add the new entry to the table */ sq_addlast((FAR sq_entry_t *)route, (FAR sq_queue_t *)&g_routes); net_unlock(save); return OK; }
struct net_pkt *net_ipv4_create_raw(struct net_pkt *pkt, const struct in_addr *src, const struct in_addr *dst, struct net_if *iface, u8_t next_header) { struct net_buf *header; header = net_pkt_get_frag(pkt, K_FOREVER); net_pkt_frag_insert(pkt, header); NET_IPV4_HDR(pkt)->vhl = 0x45; NET_IPV4_HDR(pkt)->tos = 0x00; NET_IPV4_HDR(pkt)->proto = 0; NET_IPV4_HDR(pkt)->ttl = net_if_ipv4_get_ttl(iface); NET_IPV4_HDR(pkt)->offset[0] = NET_IPV4_HDR(pkt)->offset[1] = 0; NET_IPV4_HDR(pkt)->id[0] = NET_IPV4_HDR(pkt)->id[1] = 0; net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, dst); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src, src); NET_IPV4_HDR(pkt)->proto = next_header; net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr)); net_pkt_set_family(pkt, AF_INET); net_buf_add(header, sizeof(struct net_ipv4_hdr)); return pkt; }
int udp_init(struct udp_context *ctx) { struct net_context *udp_ctx = { 0 }; struct net_context *mcast_ctx = { 0 }; struct sockaddr_in6 my_addr = { 0 }; struct sockaddr_in6 my_mcast_addr = { 0 }; int rc; k_sem_init(&ctx->rx_sem, 0, UINT_MAX); net_ipaddr_copy(&my_mcast_addr.sin6_addr, &mcast_addr); my_mcast_addr.sin6_family = AF_INET6; net_ipaddr_copy(&my_addr.sin6_addr, &server_addr); my_addr.sin6_family = AF_INET6; my_addr.sin6_port = htons(SERVER_PORT); rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &udp_ctx); if (rc < 0) { printk("Cannot get network context for IPv6 UDP (%d)", rc); return -EIO; } rc = net_context_bind(udp_ctx, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_in6)); if (rc < 0) { printk("Cannot bind IPv6 UDP port %d (%d)", SERVER_PORT, rc); goto error; } rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &mcast_ctx); if (rc < 0) { printk("Cannot get receiving IPv6 mcast (%d)", rc); goto error; } rc = net_context_bind(mcast_ctx, (struct sockaddr *)&my_mcast_addr, sizeof(struct sockaddr_in6)); if (rc < 0) { printk("Cannot get bind IPv6 mcast (%d)", rc); goto error; } ctx->rx_pkt = NULL; ctx->remaining = 0; ctx->net_ctx = udp_ctx; rc = net_context_recv(ctx->net_ctx, udp_received, K_NO_WAIT, ctx); if (rc != 0) { return -EIO; } return 0; error: net_context_put(udp_ctx); return -EINVAL; }
static inline struct net_pkt *prepare_arp_request(struct net_if *iface, struct net_pkt *req, struct net_eth_addr *addr) { struct net_pkt *pkt; struct net_buf *frag; struct net_arp_hdr *hdr, *req_hdr; struct net_eth_hdr *eth, *eth_req; pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { goto fail; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { goto fail; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); hdr = NET_ARP_HDR(pkt); eth = NET_ETH_HDR(pkt); req_hdr = NET_ARP_HDR(req); eth_req = NET_ETH_HDR(req); eth->type = htons(NET_ETH_PTYPE_ARP); memset(ð->dst.addr, 0xff, sizeof(struct net_eth_addr)); memcpy(ð->src.addr, addr, sizeof(struct net_eth_addr)); hdr->hwtype = htons(NET_ARP_HTYPE_ETH); hdr->protocol = htons(NET_ETH_PTYPE_IP); hdr->hwlen = sizeof(struct net_eth_addr); hdr->protolen = sizeof(struct in_addr); hdr->opcode = htons(NET_ARP_REQUEST); memset(&hdr->dst_hwaddr.addr, 0x00, sizeof(struct net_eth_addr)); memcpy(&hdr->src_hwaddr.addr, addr, sizeof(struct net_eth_addr)); net_ipaddr_copy(&hdr->src_ipaddr, &req_hdr->src_ipaddr); net_ipaddr_copy(&hdr->dst_ipaddr, &req_hdr->dst_ipaddr); net_buf_add(frag, sizeof(struct net_arp_hdr)); return pkt; fail: net_pkt_unref(pkt); return NULL; }
/* Setup IPv4 + UDP header */ static void setup_header(struct net_buf *buf) { struct net_ipv4_hdr *ipv4; struct net_udp_hdr *udp; uint16_t len; ipv4 = NET_IPV4_BUF(buf); udp = NET_UDP_BUF(buf); len = net_buf_frags_len(buf->frags); /* Setup IPv4 header */ memset(ipv4, 0, sizeof(struct net_ipv4_hdr)); ipv4->vhl = 0x45; ipv4->ttl = 0xFF; ipv4->proto = IPPROTO_UDP; ipv4->len[0] = len >> 8; ipv4->len[1] = (uint8_t)len; ipv4->chksum = ~net_calc_chksum_ipv4(buf); net_ipaddr_copy(&ipv4->dst, net_ipv4_broadcast_address()); len -= NET_IPV4H_LEN; /* Setup UDP header */ udp->src_port = htons(DHCPV4_CLIENT_PORT); udp->dst_port = htons(DHCPV4_SERVER_PORT); udp->len = htons(len); udp->chksum = ~net_calc_chksum_udp(buf); }
static inline void set_dst_addr(sa_family_t family, struct net_pkt *pkt, struct sockaddr *dst_addr) { net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr, &NET_IPV6_HDR(pkt)->src); net_sin6(dst_addr)->sin6_family = AF_INET6; net_sin6(dst_addr)->sin6_port = NET_UDP_HDR(pkt)->src_port; }
FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct tcp_iphdr_s *buf) { FAR struct tcp_conn_s *conn = tcp_alloc(); if (conn) { /* Fill in the necessary fields for the new connection. */ conn->rto = TCP_RTO; conn->timer = TCP_RTO; conn->sa = 0; conn->sv = 4; conn->nrtx = 0; conn->lport = buf->destport; conn->rport = buf->srcport; conn->mss = TCP_INITIAL_MSS; net_ipaddr_copy(conn->ripaddr, net_ip4addr_conv32(buf->srcipaddr)); conn->tcpstateflags = TCP_SYN_RCVD; tcp_initsequence(conn->sndseq); conn->unacked = 1; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; #endif /* rcvseq should be the seqno from the incoming packet + 1. */ memcpy(conn->rcvseq, buf->seqno, 4); #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active list. * Interrupts should already be disabled in this context. */ dq_addlast(&conn->node, &g_active_tcp_connections); } return conn; }
static inline void set_dst_addr(sa_family_t family, struct net_pkt *pkt, struct sockaddr *dst_addr) { #if defined(CONFIG_NET_IPV6) if (family == AF_INET6) { net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr, &NET_IPV6_HDR(pkt)->src); net_sin6(dst_addr)->sin6_family = AF_INET6; net_sin6(dst_addr)->sin6_port = NET_UDP_HDR(pkt)->src_port; } #endif /* CONFIG_NET_IPV6) */ #if defined(CONFIG_NET_IPV4) if (family == AF_INET) { net_ipaddr_copy(&net_sin(dst_addr)->sin_addr, &NET_IPV4_HDR(pkt)->src); net_sin(dst_addr)->sin_family = AF_INET; net_sin(dst_addr)->sin_port = NET_UDP_HDR(pkt)->src_port; } #endif /* CONFIG_NET_IPV6) */ }
static int loopback_send(struct net_if *iface, struct net_pkt *pkt) { struct net_pkt *cloned; int res; if (!pkt->frags) { SYS_LOG_ERR("No data to send"); return -ENODATA; } /* We need to swap the IP addresses because otherwise * the packet will be dropped. */ if (net_pkt_family(pkt) == AF_INET6) { struct in6_addr addr; net_ipaddr_copy(&addr, &NET_IPV6_HDR(pkt)->src); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src, &NET_IPV6_HDR(pkt)->dst); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, &addr); } else { struct in_addr addr; net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src, &NET_IPV4_HDR(pkt)->dst); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr); } /* We should simulate normal driver meaning that if the packet is * properly sent (which is always in this driver), then the packet * must be dropped. This is very much needed for TCP packets where * the packet is reference counted in various stages of sending. */ cloned = net_pkt_clone(pkt, K_MSEC(100)); if (!cloned) { res = -ENOMEM; goto out; } res = net_recv_data(iface, cloned); if (res < 0) { SYS_LOG_ERR("Data receive failed."); goto out; } net_pkt_unref(pkt); out: /* Let the receiving thread run now */ k_yield(); return res; }
static bool run_tests(void) { struct net_pkt *pkt, *pkt2; struct net_buf *frag; struct net_if *iface; struct net_if_addr *ifaddr; struct net_arp_hdr *arp_hdr; struct net_ipv4_hdr *ipv4; struct net_eth_hdr *eth_hdr; int len; struct in_addr dst = { { { 192, 168, 0, 2 } } }; struct in_addr dst_far = { { { 10, 11, 12, 13 } } }; struct in_addr dst_far2 = { { { 172, 16, 14, 186 } } }; struct in_addr src = { { { 192, 168, 0, 1 } } }; struct in_addr netmask = { { { 255, 255, 255, 0 } } }; struct in_addr gw = { { { 192, 168, 0, 42 } } }; net_arp_init(); iface = net_if_get_default(); net_if_ipv4_set_gw(iface, &gw); net_if_ipv4_set_netmask(iface, &netmask); /* Unicast test */ ifaddr = net_if_ipv4_addr_add(iface, &src, NET_ADDR_MANUAL, 0); ifaddr->addr_state = NET_ADDR_PREFERRED; /* Application data for testing */ pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { printk("Out of mem TX\n"); return false; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { printk("Out of mem DATA\n"); return false; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); setup_eth_header(iface, pkt, &hwaddr, NET_ETH_PTYPE_IP); len = strlen(app_data); if (net_pkt_ll_reserve(pkt) != sizeof(struct net_eth_hdr)) { printk("LL reserve invalid, should be %zd was %d\n", sizeof(struct net_eth_hdr), net_pkt_ll_reserve(pkt)); return false; } ipv4 = (struct net_ipv4_hdr *)net_buf_add(frag, sizeof(struct net_ipv4_hdr)); net_ipaddr_copy(&ipv4->src, &src); net_ipaddr_copy(&ipv4->dst, &dst); memcpy(net_buf_add(frag, len), app_data, len); pkt2 = net_arp_prepare(pkt); /* pkt2 is the ARP packet and pkt is the IPv4 packet and it was * stored in ARP table. */ if (pkt2 == pkt) { /* The packets cannot be the same as the ARP cache has * still room for the pkt. */ printk("ARP cache should still have free space\n"); return false; } if (!pkt2) { printk("ARP pkt is empty\n"); return false; } /* The ARP cache should now have a link to pending net_pkt * that is to be sent after we have got an ARP reply. */ if (!pkt->frags) { printk("Pending pkt fragment is NULL\n"); return false; } pending_pkt = pkt; /* pkt2 should contain the arp header, verify it */ if (memcmp(net_pkt_ll(pkt2), net_eth_broadcast_addr(), sizeof(struct net_eth_addr))) { printk("ARP ETH dest address invalid\n"); net_hexdump("ETH dest wrong ", net_pkt_ll(pkt2), sizeof(struct net_eth_addr)); net_hexdump("ETH dest correct", (u8_t *)net_eth_broadcast_addr(), sizeof(struct net_eth_addr)); return false; } if (memcmp(net_pkt_ll(pkt2) + sizeof(struct net_eth_addr), iface->link_addr.addr, sizeof(struct net_eth_addr))) { printk("ARP ETH source address invalid\n"); net_hexdump("ETH src correct", iface->link_addr.addr, sizeof(struct net_eth_addr)); net_hexdump("ETH src wrong ", net_pkt_ll(pkt2) + sizeof(struct net_eth_addr), sizeof(struct net_eth_addr)); return false; } arp_hdr = NET_ARP_HDR(pkt2); eth_hdr = NET_ETH_HDR(pkt2); if (eth_hdr->type != htons(NET_ETH_PTYPE_ARP)) { printk("ETH type 0x%x, should be 0x%x\n", eth_hdr->type, htons(NET_ETH_PTYPE_ARP)); return false; } if (arp_hdr->hwtype != htons(NET_ARP_HTYPE_ETH)) { printk("ARP hwtype 0x%x, should be 0x%x\n", arp_hdr->hwtype, htons(NET_ARP_HTYPE_ETH)); return false; } if (arp_hdr->protocol != htons(NET_ETH_PTYPE_IP)) { printk("ARP protocol 0x%x, should be 0x%x\n", arp_hdr->protocol, htons(NET_ETH_PTYPE_IP)); return false; } if (arp_hdr->hwlen != sizeof(struct net_eth_addr)) { printk("ARP hwlen 0x%x, should be 0x%zx\n", arp_hdr->hwlen, sizeof(struct net_eth_addr)); return false; } if (arp_hdr->protolen != sizeof(struct in_addr)) { printk("ARP IP addr len 0x%x, should be 0x%zx\n", arp_hdr->protolen, sizeof(struct in_addr)); return false; } if (arp_hdr->opcode != htons(NET_ARP_REQUEST)) { printk("ARP opcode 0x%x, should be 0x%x\n", arp_hdr->opcode, htons(NET_ARP_REQUEST)); return false; } if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr, &NET_IPV4_HDR(pkt)->dst)) { char out[sizeof("xxx.xxx.xxx.xxx")]; snprintk(out, sizeof(out), "%s", net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr)); printk("ARP IP dest invalid %s, should be %s", out, net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->dst)); return false; } if (!net_ipv4_addr_cmp(&arp_hdr->src_ipaddr, &NET_IPV4_HDR(pkt)->src)) { char out[sizeof("xxx.xxx.xxx.xxx")]; snprintk(out, sizeof(out), "%s", net_sprint_ipv4_addr(&arp_hdr->src_ipaddr)); printk("ARP IP src invalid %s, should be %s", out, net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src)); return false; } /* We could have send the new ARP request but for this test we * just free it. */ net_pkt_unref(pkt2); if (pkt->ref != 2) { printk("ARP cache should own the original packet\n"); return false; } /* Then a case where target is not in the same subnet */ net_ipaddr_copy(&ipv4->dst, &dst_far); pkt2 = net_arp_prepare(pkt); if (pkt2 == pkt) { printk("ARP cache should not find anything\n"); return false; } if (!pkt2) { printk("ARP pkt2 is empty\n"); return false; } arp_hdr = NET_ARP_HDR(pkt2); if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr, &iface->ipv4.gw)) { char out[sizeof("xxx.xxx.xxx.xxx")]; snprintk(out, sizeof(out), "%s", net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr)); printk("ARP IP dst invalid %s, should be %s\n", out, net_sprint_ipv4_addr(&iface->ipv4.gw)); return false; } net_pkt_unref(pkt2); /* Try to find the same destination again, this should fail as there * is a pending request in ARP cache. */ net_ipaddr_copy(&ipv4->dst, &dst_far); /* Make sure prepare will not free the pkt because it will be * needed in the later test case. */ net_pkt_ref(pkt); pkt2 = net_arp_prepare(pkt); if (!pkt2) { printk("ARP cache is not sending the request again\n"); return false; } net_pkt_unref(pkt2); /* Try to find the different destination, this should fail too * as the cache table should be full. */ net_ipaddr_copy(&ipv4->dst, &dst_far2); /* Make sure prepare will not free the pkt because it will be * needed in the next test case. */ net_pkt_ref(pkt); pkt2 = net_arp_prepare(pkt); if (!pkt2) { printk("ARP cache did not send a req\n"); return false; } /* Restore the original address so that following test case can * work properly. */ net_ipaddr_copy(&ipv4->dst, &dst); /* The arp request packet is now verified, create an arp reply. * The previous value of pkt is stored in arp table and is not lost. */ pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { printk("Out of mem RX reply\n"); return false; } printk("%d pkt %p\n", __LINE__, pkt); frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { printk("Out of mem DATA reply\n"); return false; } printk("%d frag %p\n", __LINE__, frag); net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); arp_hdr = NET_ARP_HDR(pkt); net_buf_add(frag, sizeof(struct net_arp_hdr)); net_ipaddr_copy(&arp_hdr->dst_ipaddr, &dst); net_ipaddr_copy(&arp_hdr->src_ipaddr, &src); pkt2 = prepare_arp_reply(iface, pkt, &hwaddr); if (!pkt2) { printk("ARP reply generation failed."); return false; } /* The pending packet should now be sent */ switch (net_arp_input(pkt2)) { case NET_OK: case NET_CONTINUE: break; case NET_DROP: break; } /* Yielding so that network interface TX thread can proceed. */ k_yield(); if (send_status < 0) { printk("ARP reply was not sent\n"); return false; } if (pkt->ref != 1) { printk("ARP cache should no longer own the original packet\n"); return false; } net_pkt_unref(pkt); /* Then feed in ARP request */ pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { printk("Out of mem RX request\n"); return false; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { printk("Out of mem DATA request\n"); return false; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); send_status = -EINVAL; arp_hdr = NET_ARP_HDR(pkt); net_buf_add(frag, sizeof(struct net_arp_hdr)); net_ipaddr_copy(&arp_hdr->dst_ipaddr, &src); net_ipaddr_copy(&arp_hdr->src_ipaddr, &dst); setup_eth_header(iface, pkt, &hwaddr, NET_ETH_PTYPE_ARP); pkt2 = prepare_arp_request(iface, pkt, &hwaddr); if (!pkt2) { printk("ARP request generation failed."); return false; } req_test = true; switch (net_arp_input(pkt2)) { case NET_OK: case NET_CONTINUE: break; case NET_DROP: break; } /* Yielding so that network interface TX thread can proceed. */ k_yield(); if (send_status < 0) { printk("ARP req was not sent\n"); return false; } net_pkt_unref(pkt); printk("Network ARP checks passed\n"); return true; }
static void setup_ipv6_udp_long(struct net_pkt *pkt, struct in6_addr *remote_addr, struct in6_addr *local_addr, u16_t remote_port, u16_t local_port) { struct net_udp_hdr hdr, *udp_hdr; struct net_ipv6_hdr ipv6; ipv6.vtc = 0x60; ipv6.tcflow = 0; ipv6.flow = 0; ipv6.len[0] = 0; ipv6.len[1] = NET_UDPH_LEN + strlen(payload) + sizeof(ipv6_hop_by_hop_ext_hdr); ipv6.nexthdr = 0; /* HBHO */ ipv6.hop_limit = 255; net_ipaddr_copy(&ipv6.src, remote_addr); net_ipaddr_copy(&ipv6.dst, local_addr); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); hdr.src_port = htons(remote_port); hdr.dst_port = htons(local_port); net_pkt_append_all(pkt, sizeof(ipv6), (u8_t *)&ipv6, K_FOREVER); net_pkt_append_all(pkt, sizeof(ipv6_hop_by_hop_ext_hdr), ipv6_hop_by_hop_ext_hdr, K_FOREVER); net_pkt_append_all(pkt, sizeof(hdr), (u8_t *)&hdr, K_FOREVER); net_pkt_append_all(pkt, strlen(payload), (u8_t *)payload, K_FOREVER); net_pkt_set_ipv6_ext_len(pkt, sizeof(ipv6_hop_by_hop_ext_hdr)); udp_hdr = net_udp_get_hdr(pkt, &hdr); /**TESTPOINT: Check if pointer is valid*/ zassert_equal_ptr(udp_hdr, &hdr, "Invalid UDP header pointer"); udp_hdr->src_port = htons(remote_port); udp_hdr->dst_port = htons(local_port); net_udp_set_hdr(pkt, &hdr); udp_hdr = net_udp_get_hdr(pkt, &hdr); if (udp_hdr != &hdr) { TC_ERROR("Invalid UDP header pointer %p\n", udp_hdr); zassert_true(0, "exiting"); } if (udp_hdr->src_port != htons(remote_port)) { TC_ERROR("Invalid remote port, should have been %d was %d\n", remote_port, ntohs(udp_hdr->src_port)); zassert_true(0, "exiting"); } if (udp_hdr->dst_port != htons(local_port)) { TC_ERROR("Invalid local port, should have been %d was %d\n", local_port, ntohs(udp_hdr->dst_port)); zassert_true(0, "exiting"); } net_hexdump_frags("frag", pkt); }
void run_tests(void) { k_thread_priority_set(k_current_get(), K_PRIO_COOP(7)); test_failed = false; struct net_conn_handle *handlers[CONFIG_NET_MAX_CONN]; struct net_if *iface = net_if_get_default(); struct net_if_addr *ifaddr; struct ud *ud; int ret, i = 0; bool st; struct sockaddr_in6 any_addr6; const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; struct sockaddr_in6 my_addr6; struct in6_addr in6addr_my = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; struct sockaddr_in6 peer_addr6; struct in6_addr in6addr_peer = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0x4e, 0x11, 0, 0, 0x2 } } }; struct sockaddr_in any_addr4; const struct in_addr in4addr_any = { { { 0 } } }; struct sockaddr_in my_addr4; struct in_addr in4addr_my = { { { 192, 0, 2, 1 } } }; struct sockaddr_in peer_addr4; struct in_addr in4addr_peer = { { { 192, 0, 2, 9 } } }; net_ipaddr_copy(&any_addr6.sin6_addr, &in6addr_any); any_addr6.sin6_family = AF_INET6; net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my); my_addr6.sin6_family = AF_INET6; net_ipaddr_copy(&peer_addr6.sin6_addr, &in6addr_peer); peer_addr6.sin6_family = AF_INET6; net_ipaddr_copy(&any_addr4.sin_addr, &in4addr_any); any_addr4.sin_family = AF_INET; net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my); my_addr4.sin_family = AF_INET; net_ipaddr_copy(&peer_addr4.sin_addr, &in4addr_peer); peer_addr4.sin_family = AF_INET; k_sem_init(&recv_lock, 0, UINT_MAX); ifaddr = net_if_ipv6_addr_add(iface, &in6addr_my, NET_ADDR_MANUAL, 0); if (!ifaddr) { printk("Cannot add %s to interface %p\n", net_sprint_ipv6_addr(&in6addr_my), iface); zassert_true(0, "exiting"); } ifaddr = net_if_ipv4_addr_add(iface, &in4addr_my, NET_ADDR_MANUAL, 0); if (!ifaddr) { printk("Cannot add %s to interface %p\n", net_sprint_ipv4_addr(&in4addr_my), iface); zassert_true(0, "exiting"); } #define REGISTER(family, raddr, laddr, rport, lport) \ ({ \ static struct ud user_data; \ \ user_data.remote_addr = (struct sockaddr *)raddr; \ user_data.local_addr = (struct sockaddr *)laddr; \ user_data.remote_port = rport; \ user_data.local_port = lport; \ user_data.test = "DST="#raddr"-SRC="#laddr"-RP="#rport \ "-LP="#lport; \ \ set_port(family, (struct sockaddr *)raddr, \ (struct sockaddr *)laddr, rport, lport); \ \ ret = net_udp_register((struct sockaddr *)raddr, \ (struct sockaddr *)laddr, \ rport, lport, \ test_ok, &user_data, \ &handlers[i]); \ if (ret) { \ printk("UDP register %s failed (%d)\n", \ user_data.test, ret); \ zassert_true(0, "exiting"); \ } \ user_data.handle = handlers[i++]; \ &user_data; \ }) #define REGISTER_FAIL(raddr, laddr, rport, lport) \ ret = net_udp_register((struct sockaddr *)raddr, \ (struct sockaddr *)laddr, \ rport, lport, \ test_fail, INT_TO_POINTER(0), NULL); \ if (!ret) { \ printk("UDP register invalid match %s failed\n", \ "DST="#raddr"-SRC="#laddr"-RP="#rport"-LP="#lport); \ zassert_true(0, "exiting"); \ } #define UNREGISTER(ud) \ ret = net_udp_unregister(ud->handle); \ if (ret) { \ printk("UDP unregister %p failed (%d)\n", ud->handle, \ ret); \ zassert_true(0, "exiting"); \ } #define TEST_IPV6_OK(ud, raddr, laddr, rport, lport) \ st = send_ipv6_udp_msg(iface, raddr, laddr, rport, lport, ud, \ false); \ if (!st) { \ printk("%d: UDP test \"%s\" fail\n", __LINE__, \ ud->test); \ zassert_true(0, "exiting"); \ } #define TEST_IPV6_LONG_OK(ud, raddr, laddr, rport, lport) \ st = send_ipv6_udp_long_msg(iface, raddr, laddr, rport, lport, ud, \ false); \ if (!st) { \ printk("%d: UDP long test \"%s\" fail\n", __LINE__, \ ud->test); \ zassert_true(0, "exiting"); \ } #define TEST_IPV4_OK(ud, raddr, laddr, rport, lport) \ st = send_ipv4_udp_msg(iface, raddr, laddr, rport, lport, ud, \ false); \ if (!st) { \ printk("%d: UDP test \"%s\" fail\n", __LINE__, \ ud->test); \ zassert_true(0, "exiting"); \ } #define TEST_IPV6_FAIL(ud, raddr, laddr, rport, lport) \ st = send_ipv6_udp_msg(iface, raddr, laddr, rport, lport, ud, \ true); \ if (!st) { \ printk("%d: UDP neg test \"%s\" fail\n", __LINE__, \ ud->test); \ zassert_true(0, "exiting"); \ } #define TEST_IPV4_FAIL(ud, raddr, laddr, rport, lport) \ st = send_ipv4_udp_msg(iface, raddr, laddr, rport, lport, ud, \ true); \ if (!st) { \ printk("%d: UDP neg test \"%s\" fail\n", __LINE__, \ ud->test); \ zassert_true(0, "exiting"); \ } ud = REGISTER(AF_INET6, &any_addr6, &any_addr6, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400); UNREGISTER(ud); ud = REGISTER(AF_INET, &any_addr4, &any_addr4, 1234, 4242); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 1234, 4242); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 1234, 4242); TEST_IPV4_FAIL(ud, &in4addr_peer, &in4addr_my, 1234, 4325); TEST_IPV4_FAIL(ud, &in4addr_peer, &in4addr_my, 1234, 4325); UNREGISTER(ud); ud = REGISTER(AF_INET6, &any_addr6, NULL, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400); UNREGISTER(ud); ud = REGISTER(AF_INET6, NULL, &any_addr6, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 61400); UNREGISTER(ud); ud = REGISTER(AF_INET6, &peer_addr6, &my_addr6, 1234, 4242); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 4242); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 1234, 4243); ud = REGISTER(AF_INET, &peer_addr4, &my_addr4, 1234, 4242); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 1234, 4242); TEST_IPV4_FAIL(ud, &in4addr_peer, &in4addr_my, 1234, 4243); ud = REGISTER(AF_UNSPEC, NULL, NULL, 1234, 42423); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 1234, 42423); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 42423); ud = REGISTER(AF_UNSPEC, NULL, NULL, 1234, 0); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 1234, 42422); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 42422); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 1234, 42422); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 1234, 42422); TEST_IPV4_FAIL(ud, &in4addr_peer, &in4addr_my, 12345, 42421); TEST_IPV6_FAIL(ud, &in6addr_peer, &in6addr_my, 12345, 42421); ud = REGISTER(AF_UNSPEC, NULL, NULL, 0, 0); TEST_IPV4_OK(ud, &in4addr_peer, &in4addr_my, 12345, 42421); TEST_IPV6_OK(ud, &in6addr_peer, &in6addr_my, 12345, 42421); TEST_IPV6_LONG_OK(ud, &in6addr_peer, &in6addr_my, 12345, 42421); /* Remote addr same as local addr, these two will never match */ REGISTER(AF_INET6, &my_addr6, NULL, 1234, 4242); REGISTER(AF_INET, &my_addr4, NULL, 1234, 4242); /* IPv4 remote addr and IPv6 remote addr, impossible combination */ REGISTER_FAIL(&my_addr4, &my_addr6, 1234, 4242); /**TESTPOINT: Check if tests passed*/ zassert_false(fail, "Tests failed"); i--; while (i) { ret = net_udp_unregister(handlers[i]); if (ret < 0 && ret != -ENOENT) { printk("Cannot unregister udp %d\n", i); zassert_true(0, "exiting"); } i--; } zassert_true((net_udp_unregister(NULL) < 0), "Unregister udp failed"); zassert_false(test_failed, "udp tests failed"); }
int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr_in *addr) #endif { net_lock_t flags; int port; /* The connection is expected to be in the TCP_ALLOCATED state.. i.e., * allocated via up_tcpalloc(), but not yet put into the active connections * list. */ if (!conn || conn->tcpstateflags != TCP_ALLOCATED) { return -EISCONN; } /* If the TCP port has not already been bound to a local port, then select * one now. */ flags = net_lock(); port = tcp_selectport(ntohs(conn->lport)); net_unlock(flags); if (port < 0) { return port; } /* Initialize and return the connection structure, bind it to the port number */ conn->tcpstateflags = TCP_SYN_SENT; tcp_initsequence(conn->sndseq); conn->mss = TCP_INITIAL_MSS; conn->unacked = 1; /* TCP length of the SYN is one. */ conn->nrtx = 0; conn->timer = 1; /* Send the SYN next time around. */ conn->rto = TCP_RTO; conn->sa = 0; conn->sv = 16; /* Initial value of the RTT variance. */ conn->lport = htons((uint16_t)port); #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; #endif /* The sockaddr port is 16 bits and already in network order */ conn->rport = addr->sin_port; /* The sockaddr address is 32-bits in network order. */ net_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr); #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the TCP write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active * list. Because g_active_tcp_connections is accessed from user level and * interrupt level, code, it is necessary to keep interrupts disabled during * this operation. */ flags = net_lock(); dq_addlast(&conn->node, &g_active_tcp_connections); net_unlock(flags); return OK; }
/* Check if the IPv{4|6} addresses are proper. As this can be expensive, * make this optional. */ static inline int check_ip_addr(struct net_pkt *pkt) { #if defined(CONFIG_NET_IPV6) if (net_pkt_family(pkt) == AF_INET6) { if (net_ipv6_addr_cmp(&NET_IPV6_HDR(pkt)->dst, net_ipv6_unspecified_address())) { NET_DBG("IPv6 dst address missing"); return -EADDRNOTAVAIL; } /* If the destination address is our own, then route it * back to us. */ if (net_is_ipv6_addr_loopback(&NET_IPV6_HDR(pkt)->dst) || net_is_my_ipv6_addr(&NET_IPV6_HDR(pkt)->dst)) { struct in6_addr addr; /* Swap the addresses so that in receiving side * the packet is accepted. */ net_ipaddr_copy(&addr, &NET_IPV6_HDR(pkt)->src); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src, &NET_IPV6_HDR(pkt)->dst); net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, &addr); return 1; } /* The source check must be done after the destination check * as having src ::1 is perfectly ok if dst is ::1 too. */ if (net_is_ipv6_addr_loopback(&NET_IPV6_HDR(pkt)->src)) { NET_DBG("IPv6 loopback src address"); return -EADDRNOTAVAIL; } } else #endif /* CONFIG_NET_IPV6 */ #if defined(CONFIG_NET_IPV4) if (net_pkt_family(pkt) == AF_INET) { if (net_ipv4_addr_cmp(&NET_IPV4_HDR(pkt)->dst, net_ipv4_unspecified_address())) { return -EADDRNOTAVAIL; } /* If the destination address is our own, then route it * back to us. */ if (net_is_ipv4_addr_loopback(&NET_IPV4_HDR(pkt)->dst) || net_is_my_ipv4_addr(&NET_IPV4_HDR(pkt)->dst)) { struct in_addr addr; /* Swap the addresses so that in receiving side * the packet is accepted. */ net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src, &NET_IPV4_HDR(pkt)->dst); net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr); return 1; } /* The source check must be done after the destination check * as having src 127.0.0.0/8 is perfectly ok if dst is in * localhost subnet too. */ if (net_is_ipv4_addr_loopback(&NET_IPV4_HDR(pkt)->src)) { NET_DBG("IPv4 loopback src address"); return -EADDRNOTAVAIL; } } else #endif /* CONFIG_NET_IPV4 */ { ; } return 0; }
static void set_client_address(struct sockaddr *addr, struct net_pkt *rx_pkt) { net_ipaddr_copy(&net_sin6(addr)->sin6_addr, &NET_IPV6_HDR(rx_pkt)->src); net_sin6(addr)->sin6_family = AF_INET6; net_sin6(addr)->sin6_port = NET_UDP_HDR(rx_pkt)->src_port; }
static inline bool get_context(struct net_context **udp_recv4, struct net_context **udp_recv6, struct net_context **tcp_recv4, struct net_context **tcp_recv6) { int ret; #if defined(CONFIG_NET_IPV6) struct sockaddr_in6 my_addr6 = { 0 }; #endif #if defined(CONFIG_NET_IPV4) struct sockaddr_in my_addr4 = { 0 }; #endif #if defined(CONFIG_NET_IPV6) #if !NET_BIND_ANY_ADDR net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my); #endif my_addr6.sin6_family = AF_INET6; my_addr6.sin6_port = htons(MY_PORT); #endif #if defined(CONFIG_NET_IPV4) #if !NET_BIND_ANY_ADDR net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my); #endif my_addr4.sin_family = AF_INET; my_addr4.sin_port = htons(MY_PORT); #endif #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP) ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6); if (ret < 0) { NET_ERR("Cannot get network context for IPv6 UDP (%d)", ret); return false; } net_context_setup_pools(*udp_recv6, tx_udp_slab, data_udp_pool); ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6, sizeof(struct sockaddr_in6)); if (ret < 0) { NET_ERR("Cannot bind IPv6 UDP port %d (%d)", ntohs(my_addr6.sin6_port), ret); return false; } #endif #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP) ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, udp_recv4); if (ret < 0) { NET_ERR("Cannot get network context for IPv4 UDP (%d)", ret); return false; } net_context_setup_pools(*udp_recv4, tx_udp_slab, data_udp_pool); ret = net_context_bind(*udp_recv4, (struct sockaddr *)&my_addr4, sizeof(struct sockaddr_in)); if (ret < 0) { NET_ERR("Cannot bind IPv4 UDP port %d (%d)", ntohs(my_addr4.sin_port), ret); return false; } #endif #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP) if (tcp_recv6) { ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, tcp_recv6); if (ret < 0) { NET_ERR("Cannot get network context " "for IPv6 TCP (%d)", ret); return false; } net_context_setup_pools(*tcp_recv6, tx_tcp_slab, data_tcp_pool); ret = net_context_bind(*tcp_recv6, (struct sockaddr *)&my_addr6, sizeof(struct sockaddr_in6)); if (ret < 0) { NET_ERR("Cannot bind IPv6 TCP port %d (%d)", ntohs(my_addr6.sin6_port), ret); return false; } ret = net_context_listen(*tcp_recv6, 0); if (ret < 0) { NET_ERR("Cannot listen IPv6 TCP (%d)", ret); return false; } } #endif #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP) if (tcp_recv4) { ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, tcp_recv4); if (ret < 0) { NET_ERR("Cannot get network context for IPv4 TCP"); return false; } net_context_setup_pools(*tcp_recv4, tx_tcp_slab, data_tcp_pool); ret = net_context_bind(*tcp_recv4, (struct sockaddr *)&my_addr4, sizeof(struct sockaddr_in)); if (ret < 0) { NET_ERR("Cannot bind IPv4 TCP port %d", ntohs(my_addr4.sin_port)); return false; } ret = net_context_listen(*tcp_recv4, 0); if (ret < 0) { NET_ERR("Cannot listen IPv4 TCP"); return false; } } #endif return true; }
void icmp_send(FAR struct net_driver_s *dev, FAR net_ipaddr_t *destaddr) { FAR struct icmp_iphdr_s *picmp = ICMPBUF; if (dev->d_sndlen > 0) { /* The total length to send is the size of the application data plus * the IP and ICMP headers (and, eventually, the Ethernet header) */ dev->d_len = dev->d_sndlen + IPICMP_HDRLEN; /* The total size of the data (for ICMP checksum calculation) includes * the size of the ICMP header */ dev->d_sndlen += ICMP_HDRLEN; /* Initialize the IP header. Note that for IPv6, the IP length field * does not include the IPv6 IP header length. */ #ifdef CONFIG_NET_IPv6 picmp->vtc = 0x60; picmp->tcf = 0x00; picmp->flow = 0x00; picmp->len[0] = (dev->d_sndlen >> 8); picmp->len[1] = (dev->d_sndlen & 0xff); picmp->nexthdr = IP_PROTO_ICMP; picmp->hoplimit = IP_TTL; net_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); net_ipaddr_copy(picmp->destipaddr, destaddr); #else /* CONFIG_NET_IPv6 */ picmp->vhl = 0x45; picmp->tos = 0; picmp->len[0] = (dev->d_len >> 8); picmp->len[1] = (dev->d_len & 0xff); ++g_ipid; picmp->ipid[0] = g_ipid >> 8; picmp->ipid[1] = g_ipid & 0xff; picmp->ipoffset[0] = TCPFLAG_DONTFRAG >> 8; picmp->ipoffset[1] = TCPFLAG_DONTFRAG & 0xff; picmp->ttl = IP_TTL; picmp->proto = IP_PROTO_ICMP; net_ipaddr_hdrcopy(picmp->srcipaddr, &dev->d_ipaddr); net_ipaddr_hdrcopy(picmp->destipaddr, destaddr); /* Calculate IP checksum. */ picmp->ipchksum = 0; picmp->ipchksum = ~(ip_chksum(dev)); #endif /* CONFIG_NET_IPv6 */ /* Calculate the ICMP checksum. */ picmp->icmpchksum = 0; picmp->icmpchksum = ~(icmp_chksum(dev, dev->d_sndlen)); if (picmp->icmpchksum == 0) { picmp->icmpchksum = 0xffff; } nllvdbg("Outgoing ICMP packet length: %d (%d)\n", dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); #ifdef CONFIG_NET_STATISTICS g_netstats.icmp.sent++; g_netstats.ip.sent++; #endif }
void udp_send(struct net_driver_s *dev, struct udp_conn_s *conn) { FAR struct udp_iphdr_s *pudpbuf = UDPBUF; if (dev->d_sndlen > 0) { /* The total length to send is the size of the application data plus * the IP and UDP headers (and, eventually, the Ethernet header) */ dev->d_len = dev->d_sndlen + IPUDP_HDRLEN; /* Initialize the IP header. Note that for IPv6, the IP length field * does not include the IPv6 IP header length. */ #ifdef CONFIG_NET_IPv6 pudpbuf->vtc = 0x60; pudpbuf->tcf = 0x00; pudpbuf->flow = 0x00; pudpbuf->len[0] = (dev->d_sndlen >> 8); pudpbuf->len[1] = (dev->d_sndlen & 0xff); pudpbuf->nexthdr = IP_PROTO_UDP; pudpbuf->hoplimit = conn->ttl; net_ipaddr_copy(pudpbuf->srcipaddr, &dev->d_ipaddr); net_ipaddr_copy(pudpbuf->destipaddr, &conn->ripaddr); #else /* CONFIG_NET_IPv6 */ pudpbuf->vhl = 0x45; pudpbuf->tos = 0; pudpbuf->len[0] = (dev->d_len >> 8); pudpbuf->len[1] = (dev->d_len & 0xff); ++g_ipid; pudpbuf->ipid[0] = g_ipid >> 8; pudpbuf->ipid[1] = g_ipid & 0xff; pudpbuf->ipoffset[0] = 0; pudpbuf->ipoffset[1] = 0; pudpbuf->ttl = conn->ttl; pudpbuf->proto = IP_PROTO_UDP; net_ipaddr_hdrcopy(pudpbuf->srcipaddr, &dev->d_ipaddr); net_ipaddr_hdrcopy(pudpbuf->destipaddr, &conn->ripaddr); /* Calculate IP checksum. */ pudpbuf->ipchksum = 0; pudpbuf->ipchksum = ~(ip_chksum(dev)); #endif /* CONFIG_NET_IPv6 */ /* Initialize the UDP header */ pudpbuf->srcport = conn->lport; pudpbuf->destport = conn->rport; pudpbuf->udplen = HTONS(dev->d_sndlen + UDP_HDRLEN); #ifdef CONFIG_NET_UDP_CHECKSUMS /* Calculate UDP checksum. */ pudpbuf->udpchksum = 0; pudpbuf->udpchksum = ~(udp_chksum(dev)); if (pudpbuf->udpchksum == 0) { pudpbuf->udpchksum = 0xffff; } #else pudpbuf->udpchksum = 0; #endif nllvdbg("Outgoing UDP packet length: %d (%d)\n", dev->d_len, (pudpbuf->len[0] << 8) | pudpbuf->len[1]); #ifdef CONFIG_NET_STATISTICS g_netstats.udp.sent++; g_netstats.ip.sent++; #endif }
static inline bool get_context(struct net_context **udp_recv6, struct net_context **tcp_recv6, struct net_context **mcast_recv6) { int ret; struct sockaddr_in6 mcast_addr6 = { 0 }; struct sockaddr_in6 my_addr6 = { 0 }; net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast); mcast_addr6.sin6_family = AF_INET6; my_addr6.sin6_family = AF_INET6; my_addr6.sin6_port = htons(MY_PORT); ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6); if (ret < 0) { printk("Cannot get network context for IPv6 UDP (%d)", ret); return false; } ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6, sizeof(struct sockaddr_in6)); if (ret < 0) { printk("Cannot bind IPv6 UDP port %d (%d)", ntohs(my_addr6.sin6_port), ret); return false; } ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6); if (ret < 0) { printk("Cannot get receiving IPv6 mcast " "network context (%d)", ret); return false; } ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6, sizeof(struct sockaddr_in6)); if (ret < 0) { printk("Cannot bind IPv6 mcast (%d)", ret); return false; } ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, tcp_recv6); if (ret < 0) { printk("Cannot get network context for IPv6 TCP (%d)", ret); return false; } net_context_setup_pools(*tcp_recv6, tx_tcp_pool, data_tcp_pool); ret = net_context_bind(*tcp_recv6, (struct sockaddr *)&my_addr6, sizeof(struct sockaddr_in6)); if (ret < 0) { printk("Cannot bind IPv6 TCP port %d (%d)", ntohs(my_addr6.sin6_port), ret); return false; } ret = net_context_listen(*tcp_recv6, 0); if (ret < 0) { printk("Cannot listen IPv6 TCP (%d)", ret); return false; } return true; }