バックナンバーはこちら。
https://www.simulationroom999.com/blog/In-vehicle-network-backnumber/
はじめに
lwIPの疑似受信用のソースコード。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
lwIPの疑似受信
太郎くん
そういえば、今回は「疑似受信」って言い方だね。
いつもだと「シミュレーション」とか言いそうなのに。
フクさん
シミュレーションでも良いけど、
まぁ目的はIPフラグメントの解決だけだしねー。
シミュレーションってほどではないだろう。
太郎くん
まぁlwIPを使ってはいるけど、
プロトコルスタックを純粋に再現してるわけでもないから、
確かにそうかも。
lwIPの疑似受信用コード
フクさん
というわけで作ったコードはこれだ!
#include <Windows.h>
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/dns.h"
#include "netif/etharp.h"
#if LWIP_IPV6
#include "lwip/ethip6.h"
#include "lwip/nd6.h"
#endif
#include "lwip/apps/httpd.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/lwiperf.h"
#include "lwip/apps/mdns.h"
#include "lwip/apps/netbiosns.h"
#include <string.h>
#include <stdio.h>
/* This define enables multi packet processing.
* For this, the input is interpreted as 2 byte length + data + 2 byte length + data...
* #define LWIP_FUZZ_MULTI_PACKET
*/
u8_t pktbuf[20000];
/* no-op send function */
static err_t lwip_tx_func(struct netif *netif, struct pbuf *p)
{
BYTE *pbuf;
int i;
int cnt = 0;
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(p);
return ERR_OK;
}
static err_t testif_init(struct netif *netif)
{
netif->name[0] = 't';
netif->name[1] = 's';
netif->output = etharp_output;
netif->linkoutput = lwip_tx_func;
netif->mtu = 1500;
netif->hwaddr_len = 6;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
netif->hwaddr[0] = 0x00;
netif->hwaddr[1] = 0x23;
netif->hwaddr[2] = 0xC1;
netif->hwaddr[3] = 0xDE;
netif->hwaddr[4] = 0xD0;
netif->hwaddr[5] = 0x0D;
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
netif->ip6_autoconfig_enabled = 1;
netif_create_ip6_linklocal_address(netif, 1);
netif->flags |= NETIF_FLAG_MLD6;
#endif
return ERR_OK;
}
static void input_pkt(struct netif *netif, const u8_t *data, size_t len)
{
struct pbuf *p, *q;
err_t err;
LWIP_ASSERT("pkt too big", len <= 0xFFFF);
p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL);
LWIP_ASSERT("alloc failed", p);
for(q = p; q != NULL; q = q->next) {
MEMCPY(q->payload, data, q->len);
data += q->len;
}
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
}
static void input_pkts(struct netif *netif, const u8_t *data, size_t len)
{
input_pkt(netif, data, len);
}
u32_t sys_now(void)
{
return GetTickCount();
}
void * sio_open(u8_t devnum)
{
return NULL;
}
void sio_send(u8_t c, void* fd)
{
}
u32_t sio_tryread(void* fd, u8_t *data, u32_t len)
{
return 0;
}
#include "lwip/udp.h"
#include "lwip/igmp.h"
struct test_udp_rxdata {
u32_t rx_cnt;
u32_t rx_bytes;
struct udp_pcb *pcb;
};
static struct netif test_netif1;
static void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
const ip_addr_t *addr, u16_t port)
{
struct test_udp_rxdata *ctr = (struct test_udp_rxdata *)arg;
int i;
int cnt = 0;
BYTE *pbuf;
LWIP_UNUSED_ARG(addr);
LWIP_UNUSED_ARG(port);
ctr->rx_cnt++;
ctr->rx_bytes += p->tot_len;
do {
pbuf = (BYTE*)p->payload;
for( i =0 ; i < p->len; i++ ){
printf("%02X ", pbuf[i]);
if ( (cnt % 16) == 15) printf("\n");
cnt++;
}
p = p->next;
}while( p != NULL );
printf("\n\n");
if (p != NULL) {
pbuf_free(p);
}
}
BYTE txdata1[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,0xdc,0x20,0x00,0xff,0x11,0x6a,0x0f,0xc0,0xa8,0x0A,0x0B,0xec,0x00,0x01,0x01,0xb0,0x00,0x09,0x79,0x2a,0x6d,0x00,0x00,0x01,…};
BYTE txdata2[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,0xdc,0x20,0xb9,0xff,0x11,0x69,0x56,0xc0,0xa8,0x0A,0x0B,0xec,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,…};
BYTE txdata3[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,…};
BYTE txdata4[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,…};
BYTE txdata5[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,…};
BYTE txdata6[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,…};
BYTE txdata7[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x05,0xdc,0x6a,…};
BYTE txdata8[] = {0x01,0x00,0x5e,0x00,0x01,0x01,0x10,0x6f,0x3f,0x0f,0xd6,0xdd,0x08,0x00,0x45,0x00,0x02,0x09,0x6a,…};
int main(int argc, char** argv)
{
struct netif net_test;
ip4_addr_t addr;
ip4_addr_t netmask;
ip4_addr_t gw;
size_t len;
err_t err;
struct udp_pcb *pcb1, *pcb2;
const u16_t port = 2425;
struct test_udp_rxdata ctr1;
struct pbuf *p;
lwip_init();
IP4_ADDR(&netmask, 0, 0, 0, 0);
IP4_ADDR(&gw, 192, 168, 10, 1);
netif_add(&net_test, NULL, NULL, NULL, /*&net_test*/NULL, testif_init, ethernet_input);
IP4_ADDR(&addr, 236, 0, 1, 1);
igmp_joingroup_netif(&net_test, &addr);
netif_set_up(&net_test);
netif_set_link_up(&net_test);
/* initialize apps */
pcb1 = udp_new();
err = udp_bind(pcb1, &test_netif1.ip_addr, port);
memset(&ctr1, 0, sizeof(ctr1));
ctr1.pcb = pcb1;
udp_recv(pcb1, test_recv, &ctr1);
input_pkts(&net_test, txdata1, sizeof(txdata1));
input_pkts(&net_test, txdata2, sizeof(txdata2));
input_pkts(&net_test, txdata3, sizeof(txdata3));
input_pkts(&net_test, txdata4, sizeof(txdata4));
input_pkts(&net_test, txdata5, sizeof(txdata5));
input_pkts(&net_test, txdata6, sizeof(txdata6));
input_pkts(&net_test, txdata7, sizeof(txdata7));
input_pkts(&net_test, txdata8, sizeof(txdata8));
return 0;
}
コード説明
太郎くん
長い!!
フクさん
ちなみに、EthernetFrameはBYTE配列でそのまま定義した。
長いんで省略してる。
太郎くん
ポイントだけ説明よろしく!
フクさん
まぁポイントはmain関数見てって程度だねー。
main関数の中身は前回までに説明したlwIPのAPIを使ってるだけだ。
あとはinput_pktsって関数にEthernetFrameを渡せば受信したことになる。
太郎くん
まぁあとは実際に動かす感じかなー。
まとめ
フクさん
まとめだよ。
- lwIP疑似受信用のソースコード。
- 詳細は前回までのlwIPのAPI説明を参照願う。
バックナンバーはこちら。
コメント