📄 icmp.c
字号:
#endif
bf_afree(ip_data);
bf_afree(icmp_data);
return;
}
if (icmp_len < ICMP_MIN_HDR_LEN + sizeof(icmp_id_seq_t))
{
#if DEBUG
{ where(); printf("got an incomplete icmp echo request\n"); }
#endif
bf_afree(ip_data);
bf_afree(icmp_data);
return;
}
#if DEBUG & 256
{ where(); printf("got an icmp echo request, ident= %u, seq= %u\n",
ntohs(icmp_hdr->ih_hun.ihh_idseq.iis_id),
ntohs(icmp_hdr->ih_hun.ihh_idseq.iis_seq)); }
#endif
repl_ip_hdr= make_repl_ip(ip_hdr, ip_len);
repl_icmp= bf_memreq (ICMP_MIN_HDR_LEN);
assert (repl_icmp->acc_length == ICMP_MIN_HDR_LEN);
repl_icmp_hdr= (icmp_hdr_t *)ptr2acc_data(repl_icmp);
repl_icmp_hdr->ih_type= ICMP_TYPE_ECHO_REPL;
repl_icmp_hdr->ih_code= 0;
tmp_chksum= ~icmp_hdr->ih_chksum - *(u16_t *)&icmp_hdr->ih_type+
*(u16_t *)&repl_icmp_hdr->ih_type;
tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);
tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);
repl_icmp_hdr->ih_chksum= ~tmp_chksum;
repl_ip_hdr->acc_next= repl_icmp;
repl_icmp->acc_next= bf_cut (icmp_data, ICMP_MIN_HDR_LEN,
icmp_len - ICMP_MIN_HDR_LEN);
bf_afree(ip_data);
bf_afree(icmp_data);
enqueue_pack(icmp_port, repl_ip_hdr);
}
PRIVATE u16_t icmp_pack_oneCsum(icmp_pack)
acc_t *icmp_pack;
{
u16_t prev;
int odd_byte;
char *data_ptr;
int length;
char byte_buf[2];
assert (icmp_pack);
prev= 0;
odd_byte= FALSE;
for (; icmp_pack; icmp_pack= icmp_pack->acc_next)
{
data_ptr= ptr2acc_data(icmp_pack);
length= icmp_pack->acc_length;
if (!length)
continue;
if (odd_byte)
{
byte_buf[1]= *data_ptr;
prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
data_ptr++;
length--;
odd_byte= FALSE;
}
if (length & 1)
{
odd_byte= TRUE;
length--;
byte_buf[0]= data_ptr[length];
}
if (!length)
continue;
prev= oneC_sum (prev, (u16_t *)data_ptr, length);
}
if (odd_byte)
prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
return prev;
}
PRIVATE acc_t *make_repl_ip(ip_hdr, ip_len)
ip_hdr_t *ip_hdr;
int ip_len;
{
ip_hdr_t *repl_ip_hdr;
acc_t *repl;
int repl_hdr_len;
if (ip_len>IP_MIN_HDR_SIZE)
{
#if DEBUG
{ where(); printf("ip_hdr options NOT supported (yet?)\n"); }
#endif
ip_len= IP_MIN_HDR_SIZE;
}
repl_hdr_len= IP_MIN_HDR_SIZE;
repl= bf_memreq(repl_hdr_len);
assert (repl->acc_length == repl_hdr_len);
repl_ip_hdr= (ip_hdr_t *)ptr2acc_data(repl);
repl_ip_hdr->ih_vers_ihl= repl_hdr_len >> 2;
repl_ip_hdr->ih_tos= ip_hdr->ih_tos;
repl_ip_hdr->ih_ttl= ICMP_DEF_TTL;
repl_ip_hdr->ih_proto= IPPROTO_ICMP;
repl_ip_hdr->ih_dst= ip_hdr->ih_src;
repl_ip_hdr->ih_flags_fragoff= 0;
return repl;
}
PRIVATE void enqueue_pack(icmp_port, reply_ip_hdr)
icmp_port_t *icmp_port;
acc_t *reply_ip_hdr;
{
reply_ip_hdr->acc_ext_link= 0;
if (icmp_port->icp_head_queue)
{
icmp_port->icp_tail_queue->acc_ext_link=
reply_ip_hdr;
}
else
{
icmp_port->icp_head_queue= reply_ip_hdr;
icmp_port->icp_tail_queue= reply_ip_hdr;
}
if (!(icmp_port->icp_flags & ICPF_WRITE_IP))
icmp_write(icmp_port);
}
PRIVATE void icmp_write(icmp_port)
icmp_port_t *icmp_port;
{
int result;
assert (!(icmp_port->icp_flags & (ICPF_WRITE_IP|ICPF_WRITE_SP) ||
(icmp_port->icp_flags & (ICPF_WRITE_IP|ICPF_WRITE_SP)) ==
(ICPF_WRITE_IP|ICPF_WRITE_SP)));
for (;icmp_port->icp_head_queue;)
{
icmp_port->icp_write_pack= icmp_port->icp_head_queue;
icmp_port->icp_head_queue= icmp_port->icp_head_queue->
acc_ext_link;
icmp_port->icp_flags |= ICPF_WRITE_IP;
icmp_port->icp_flags &= ~ICPF_WRITE_SP;
#if DEBUG & 256
{ where(); printf("calling ip_write\n"); }
#endif
result= ip_write(icmp_port->icp_ipfd,
bf_bufsize(icmp_port->icp_write_pack));
if (result == NW_SUSPEND)
{
#if DEBUG & 256
{ where(); printf("ip_write replied NW_SUSPEND\n"); }
#endif
icmp_port->icp_flags |= ICPF_WRITE_SP;
return;
}
#if DEBUG & 256
{ where(); printf("ip_write done\n"); }
#endif
}
icmp_port->icp_flags &= ~ICPF_WRITE_IP;
}
PRIVATE void icmp_buffree(priority, reqsize)
int priority;
size_t reqsize;
{
acc_t *tmp_acc;
int donesomething,i;
icmp_port_t *icmp_port;
donesomething= 0;
if (priority < ICMP_PRI_QUEUE)
return;
while (bf_free_buffsize < reqsize)
{
for (i=0, icmp_port= icmp_port_table; i<ICMP_PORT_NR;
i++, icmp_port++)
{
if (icmp_port->icp_head_queue)
{
tmp_acc= icmp_port->icp_head_queue;
icmp_port->icp_head_queue= tmp_acc->
acc_ext_link;
bf_afree(tmp_acc);
if (bf_free_buffsize >= reqsize)
break;
donesomething= 1;
}
}
if (!donesomething)
break;
}
}
static void icmp_dst_unreach(icmp_port, ip_pack, ip_hdr_len, ip_hdr, icmp_pack,
icmp_len, icmp_hdr)
icmp_port_t *icmp_port;
acc_t *ip_pack;
int ip_hdr_len;
ip_hdr_t *ip_hdr;
acc_t *icmp_pack;
int icmp_len;
icmp_hdr_t *icmp_hdr;
{
acc_t *old_ip_pack;
ip_hdr_t *old_ip_hdr;
if (icmp_len < 8 + IP_MIN_HDR_SIZE)
{
#if DEBUG
{ where(); printf("dest unrch with wrong size\n"); }
#endif
return;
}
old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
if (old_ip_hdr->ih_src != ip_hdr->ih_dst)
{
#if DEBUG
{ where(); printf("dest unrch based on wrong packet\n"); }
#endif
bf_afree(old_ip_pack);
return;
}
switch(icmp_hdr->ih_code)
{
case ICMP_NET_UNRCH:
ipr_destunrch (old_ip_hdr->ih_dst,
ip_get_netmask(old_ip_hdr->ih_dst), IPR_UNRCH_TIMEOUT);
break;
case ICMP_HOST_UNRCH:
ipr_destunrch (old_ip_hdr->ih_dst, (ipaddr_t)-1,
IPR_UNRCH_TIMEOUT);
break;
default:
#if DEBUG
{ where(); printf("got strange code: %d\n", icmp_hdr->ih_code); }
#endif
break;
}
bf_afree(old_ip_pack);
}
static void icmp_time_exceeded(icmp_port, ip_pack, ip_hdr_len, ip_hdr,
icmp_pack, icmp_len, icmp_hdr)
icmp_port_t *icmp_port;
acc_t *ip_pack;
int ip_hdr_len;
ip_hdr_t *ip_hdr;
acc_t *icmp_pack;
int icmp_len;
icmp_hdr_t *icmp_hdr;
{
acc_t *old_ip_pack;
ip_hdr_t *old_ip_hdr;
if (icmp_len < 8 + IP_MIN_HDR_SIZE)
{
#if DEBUG
{ where(); printf("time exceeded with wrong size\n"); }
#endif
return;
}
old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
if (old_ip_hdr->ih_src != ip_hdr->ih_dst)
{
#if DEBUG
{ where(); printf("time exceeded based on wrong packet\n"); }
#endif
bf_afree(old_ip_pack);
return;
}
switch(icmp_hdr->ih_code)
{
case ICMP_TTL_EXC:
ipr_ttl_exc (old_ip_hdr->ih_dst, (ipaddr_t)-1,
IPR_TTL_TIMEOUT);
break;
default:
where();
printf("got strange code: %d\n", icmp_hdr->ih_code);
break;
}
bf_afree(old_ip_pack);
}
static void icmp_router_advertisement(icmp_port, icmp_pack, icmp_len, icmp_hdr)
icmp_port_t *icmp_port;
acc_t *icmp_pack;
int icmp_len;
icmp_hdr_t *icmp_hdr;
{
int entries;
int entry_size;
u16_t lifetime;
int i;
char *bufp;
if (icmp_len < 8)
{
#if DEBUG
{ where(); printf("router advertisement with wrong size (%d)\n", icmp_len); }
#endif
return;
}
if (icmp_hdr->ih_code != 0)
{
#if DEBUG
{ where(); printf("router advertisement with wrong code (%d)\n",
icmp_hdr->ih_code); }
#endif
return;
}
entries= icmp_hdr->ih_hun.ihh_ram.iram_na;
entry_size= icmp_hdr->ih_hun.ihh_ram.iram_aes * 4;
if (entries < 1)
{
#if DEBUG
{ where(); printf("router advertisement with wrong number of entries (%d)\n",
entries); }
#endif
return;
}
if (entry_size < 8)
{
#if DEBUG
{ where(); printf("router advertisement with wrong entry size (%d)\n",
entry_size); }
#endif
return;
}
if (icmp_len < 8 + entries * entry_size)
{
#if DEBUG
{ where(); printf("router advertisement with wrong size\n");
printf("\t(entries= %d, entry_size= %d, icmp_len= %d)\n", entries,
entry_size, icmp_len); }
#endif
return;
}
lifetime= ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt);
if (lifetime > 9000)
{
#if DEBUG
{ where(); printf("router advertisement with wrong lifetime (%d)\n",
lifetime); }
#endif
return;
}
for (i= 0, bufp= (char *)&icmp_hdr->ih_dun.uhd_data[0]; i< entries; i++,
bufp += entry_size)
{
ipr_add_route(HTONL(0L), HTONL(0L), *(ipaddr_t *)bufp,
icmp_port->icp_ipport, lifetime * HZ, 1, 0,
ntohl(*(i32_t *)(bufp+4)));
}
}
static void icmp_redirect(icmp_port, ip_hdr, icmp_pack, icmp_len, icmp_hdr)
icmp_port_t *icmp_port;
ip_hdr_t *ip_hdr;
acc_t *icmp_pack;
int icmp_len;
icmp_hdr_t *icmp_hdr;
{
acc_t *old_ip_pack;
ip_hdr_t *old_ip_hdr;
int port;
if (icmp_len < 8 + IP_MIN_HDR_SIZE)
{
#if DEBUG
{ where(); printf("redirect with wrong size\n"); }
#endif
return;
}
old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
port= icmp_port->icp_ipport;
switch(icmp_hdr->ih_code)
{
case ICMP_REDIRECT_NET:
ipr_redirect (old_ip_hdr->ih_dst,
ip_get_netmask(old_ip_hdr->ih_dst),
ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, port,
IPR_REDIRECT_TIMEOUT);
break;
case ICMP_REDIRECT_HOST:
ipr_redirect (old_ip_hdr->ih_dst, (ipaddr_t)-1,
ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, port,
IPR_REDIRECT_TIMEOUT);
break;
default:
where();
printf("got strange code: %d\n", icmp_hdr->ih_code);
break;
}
bf_afree(old_ip_pack);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -