void uip_build_arp_request(struct uip_stack *ustack, u16_t *ipaddr) { struct arp_hdr *arp; struct uip_eth_hdr *eth; arp = (struct arp_hdr *)ustack->network_layer; eth = (struct uip_eth_hdr *)ustack->data_link_layer; /* The destination address was not in our ARP table, so we overwrite the IP packet with an ARP request. */ memset(eth->dest.addr, 0xff, 6); memset(arp->dhwaddr.addr, 0x00, 6); memcpy(eth->src.addr, ustack->uip_ethaddr.addr, 6); memcpy(arp->shwaddr.addr, ustack->uip_ethaddr.addr, 6); uip_ip4addr_copy(arp->dipaddr, ipaddr); uip_ip4addr_copy(arp->sipaddr, ustack->hostaddr); arp->opcode = const_htons(ARP_REQUEST); /* ARP request. */ arp->hwtype = const_htons(ARP_HWTYPE_ETH); arp->protocol = const_htons(UIP_ETHTYPE_IPv4); arp->hwlen = 6; arp->protolen = 4; eth->type = const_htons(UIP_ETHTYPE_ARP); ustack->uip_appdata = &ustack->uip_buf[UIP_TCP_IPv4_HLEN + UIP_LLH_LEN]; ustack->uip_len = sizeof(*arp) + sizeof(*eth); }
/*---------------------------------------------------------------------------*/ static int prepare_and_send_buf(coap_context_t *ctx, session_t *session, uint8_t *data, size_t len) { struct net_buf *buf; int max_data_len; /* This net_buf gets sent to network, so it is not released * by this function unless there was an error and buf was * not actually sent. */ buf = ip_buf_get_tx(ctx->net_ctx); if (!buf) { len = -ENOBUFS; goto out; } max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN; PRINTF("%s: reply to peer data %p len %d\n", __FUNCTION__, data, len); if (len > max_data_len) { PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n", __FUNCTION__, len, max_data_len); ip_buf_unref(buf); len = -EINVAL; goto out; } /* Note that we have reversed the addresses here * because net_reply() will reverse them again. */ #ifdef CONFIG_NETWORKING_WITH_IPV6 uip_ip6addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip6addr_t *)&ctx->my_addr.in6_addr); uip_ip6addr_copy(&NET_BUF_IP(buf)->srcipaddr, (uip_ip6addr_t *)&session->addr.ipaddr); #else uip_ip4addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip4addr_t *)&ctx->my_addr.in_addr); uip_ip4addr_copy(&NET_BUF_IP(buf)->srcipaddr, (uip_ip4addr_t *)&session->addr.ipaddr); #endif NET_BUF_UDP(buf)->destport = uip_ntohs(ctx->my_port); NET_BUF_UDP(buf)->srcport = session->addr.port; uip_set_udp_conn(buf) = net_context_get_udp_connection(ctx->net_ctx); memcpy(net_buf_add(buf, len), data, len); ip_buf_appdatalen(buf) = len; ip_buf_appdata(buf) = buf->data + ip_buf_reserve(buf); if (net_reply(ctx->net_ctx, buf)) { ip_buf_unref(buf); } out: return len; }
dest_ipv4_addr_t uip_determine_dest_ipv4_addr(struct uip_stack *ustack, u16_t *ipaddr) { struct arp_hdr *arp; struct uip_eth_hdr *eth; struct ip_hdr *ip_buf; arp = (struct arp_hdr *)ustack->network_layer; eth = (struct uip_eth_hdr *)ustack->data_link_layer; ip_buf = (struct ip_hdr *)ustack->network_layer; /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. If not ARP table entry is found, we overwrite the original IP packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if (uip_ip4addr_cmp(ip_buf->destipaddr, broadcast_ipaddr)) { memcpy(ð->dest, broadcast_ethaddr.addr, 6); return LOCAL_BROADCAST; } else { /* Check if the destination address is on the local network. */ if (!uip_ip4addr_maskcmp(ip_buf->destipaddr, ustack->hostaddr, ustack->netmask)) { /* Destination address was not on the local network, so we need to use the default router's IP address instead of the destination address when determining the MAC address. */ uip_ip4addr_copy(ipaddr, ustack->default_route_addr); } else { /* Else, we use the destination IP address. */ uip_ip4addr_copy(ipaddr, ip_buf->destipaddr); } return NONLOCAL_BROADCAST; } }
/*---------------------------------------------------------------------------*/ struct ip64_addrmap_entry * ip64_addrmap_create(const uip_ip6addr_t *ip6addr, uint16_t ip6port, const uip_ip4addr_t *ip4addr, uint16_t ip4port, uint8_t protocol) { struct ip64_addrmap_entry *m; check_age(); m = memb_alloc(&entrymemb); if(m == NULL) { /* We could not allocate an entry, try to recycle one and try to allocate again. */ if(recycle()) { m = memb_alloc(&entrymemb); } } if(m != NULL) { uip_ip4addr_copy(&m->ip4addr, ip4addr); m->ip4port = ip4port; uip_ip6addr_copy(&m->ip6addr, ip6addr); m->ip6port = ip6port; m->protocol = protocol; m->flags = FLAGS_NONE; m->ip6to4 = 1; m->ip4to6 = 0; timer_set(&m->timer, 0); /* Pick a new, unused local port. First make sure that the mapped_port number does not belong to any active connection. If so, we keep increasing the mapped_port until we're free. */ { struct ip64_addrmap_entry *n; n = list_head(entrylist); while(n != NULL) { if(n->mapped_port == mapped_port) { increase_mapped_port(); n = list_head(entrylist); } else { n = list_item_next(m); } } } m->mapped_port = mapped_port; increase_mapped_port(); list_add(entrylist, m); return m; } return NULL; }