static rt_err_t _low_level_dhcp_send(struct netif *netif, const void *buffer, rt_size_t size) { struct pbuf *p; struct eth_hdr *ethhdr; struct ip_hdr *iphdr; struct udp_hdr *udphdr; p = pbuf_alloc(PBUF_LINK, SIZEOF_ETH_HDR + sizeof(struct ip_hdr) + sizeof(struct udp_hdr) + size, PBUF_RAM); if (p == RT_NULL) return -RT_ENOMEM; ethhdr = (struct eth_hdr *)p->payload; iphdr = (struct ip_hdr *)((char *)ethhdr + SIZEOF_ETH_HDR); udphdr = (struct udp_hdr *)((char *)iphdr + sizeof(struct ip_hdr)); ETHADDR32_COPY(ðhdr->dest, (struct eth_addr *)ðbroadcast); ETHADDR16_COPY(ðhdr->src, netif->hwaddr); ethhdr->type = PP_HTONS(ETHTYPE_IP); iphdr->src.addr = 0x00000000; /* src: 0.0.0.0 */ iphdr->dest.addr = 0xFFFFFFFF; /* src: 255.255.255.255 */ IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); IPH_TOS_SET(iphdr, 0x00); IPH_LEN_SET(iphdr, htons(IP_HLEN + sizeof(struct udp_hdr) + size)); IPH_ID_SET(iphdr, htons(2)); IPH_OFFSET_SET(iphdr, 0); IPH_TTL_SET(iphdr, 255); IPH_PROTO_SET(iphdr, IP_PROTO_UDP); IPH_CHKSUM_SET(iphdr, 0); IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); udphdr->src = htons(DHCP_SERVER_PORT); udphdr->dest = htons(DHCP_CLIENT_PORT); udphdr->len = htons(sizeof(struct udp_hdr) + size); udphdr->chksum = 0; memcpy((char *)udphdr + sizeof(struct udp_hdr), buffer, size); return netif->linkoutput(netif, p); }
static struct pbuf * test_udp_create_test_packet(u16_t length, u16_t port, u32_t dst_addr) { err_t err; u8_t ret; struct udp_hdr *uh; struct ip_hdr *ih; struct pbuf *p; const u8_t test_data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL); fail_unless(p != NULL); if (p == NULL) { return NULL; } fail_unless(p->next == NULL); err = pbuf_take(p, test_data, length); fail_unless(err == ERR_OK); /* add UDP header */ ret = pbuf_add_header(p, sizeof(struct udp_hdr)); fail_unless(!ret); uh = (struct udp_hdr *)p->payload; uh->chksum = 0; uh->dest = uh->src = lwip_htons(port); uh->len = lwip_htons(p->tot_len); /* add IPv4 header */ ret = pbuf_add_header(p, sizeof(struct ip_hdr)); fail_unless(!ret); ih = (struct ip_hdr *)p->payload; memset(ih, 0, sizeof(*ih)); ih->dest.addr = dst_addr; ih->_len = lwip_htons(p->tot_len); ih->_ttl = 32; ih->_proto = IP_PROTO_UDP; IPH_VHL_SET(ih, 4, sizeof(struct ip_hdr) / 4); IPH_CHKSUM_SET(ih, inet_chksum(ih, sizeof(struct ip_hdr))); return p; }
/** Create a TCP segment usable for passing to tcp_input */ static struct pbuf* tcp_create_segment_wnd(ip_addr_t* src_ip, ip_addr_t* dst_ip, u16_t src_port, u16_t dst_port, void* data, size_t data_len, u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd) { struct pbuf *p, *q; struct ip_hdr* iphdr; struct tcp_hdr* tcphdr; u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len); LWIP_ASSERT("data_len too big", data_len <= 0xFFFF); p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL); EXPECT_RETNULL(p != NULL); /* first pbuf must be big enough to hold the headers */ EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); if (data_len > 0) { /* first pbuf must be big enough to hold at least 1 data byte, too */ EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); } for(q = p; q != NULL; q = q->next) { memset(q->payload, 0, q->len); } iphdr = (struct ip_hdr*)p->payload; /* fill IP header */ iphdr->dest.addr = ip_2_ip4(dst_ip)->addr; iphdr->src.addr = ip_2_ip4(src_ip)->addr; IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); IPH_TOS_SET(iphdr, 0); IPH_LEN_SET(iphdr, htons(p->tot_len)); IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); /* let p point to TCP header */ pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); tcphdr = (struct tcp_hdr*)p->payload; tcphdr->src = htons(src_port); tcphdr->dest = htons(dst_port); tcphdr->seqno = htonl(seqno); tcphdr->ackno = htonl(ackno); TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4); TCPH_FLAGS_SET(tcphdr, headerflags); tcphdr->wnd = htons(wnd); if (data_len > 0) { /* let p point to TCP data */ pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr)); /* copy data */ pbuf_take(p, data, (u16_t)data_len); /* let p point to TCP header again */ pbuf_header(p, sizeof(struct tcp_hdr)); } /* calculate checksum */ tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, src_ip, dst_ip); pbuf_header(p, sizeof(struct ip_hdr)); return p; }