📄 ip.c
字号:
/* ip_input:
*
* This function is called by the network interface device driver when
* an IP packet is received. The function does the basic checks of the
* IP header such as packet size being at least larger than the header
* size etc. If the packet was not destined for us, the packet is
* forwarded (using ip_forward). The IP checksum is always checked.
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
u8_t cnt;
static struct ip_hdr *iphdr;
static struct netif *netif;
static u8_t hl;
#ifdef IP_STATS
++stats.ip.recv;
#endif /* IP_STATS */
/* identify the IP header */
iphdr = p->payload;
if(IPH_V(iphdr) != 4) {
DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number %d\n", IPH_V(iphdr)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
#ifdef LCD_DEBUG_IP
Put_String("\nIP: error IPV");
#endif
pbuf_free(p);
#ifdef IP_STATS
++stats.ip.err;
++stats.ip.drop;
#endif /* IP_STATS */
return ERR_OK;
}
hl = IPH_HL(iphdr);
if(hl * 4 > p->len) {
DEBUGF(IP_DEBUG, ("IP packet dropped due to too short packet %d\n", p->len));
#ifdef LCD_DEBUG_IP
Put_String("\nIP: inval. len");
#endif
pbuf_free(p);
#ifdef IP_STATS
++stats.ip.lenerr;
++stats.ip.drop;
#endif /* IP_STATS */
return ERR_OK;
}
// SetCur(1,0);
/* verify checksum */
if(inet_chksum(iphdr, hl * 4) != 0) {
// SetCur(1,0);
#ifdef LCD_DEBUG_IP
Put_String("\nIP: err cs");
#endif
DEBUGF(IP_DEBUG, ("IP packet dropped due to failing checksum 0x%x\n", inet_chksum(iphdr, hl * 4)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++stats.ip.chkerr;
++stats.ip.drop;
#endif /* IP_STATS */
return ERR_OK;
}
/* Trim pbuf. This should have been done at the netif layer,
but we'll do it anyway just to be sure that its done. */
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
// SetCur(1,0);
//Put_String(" ");
/* is this packet for us? */
for(netif = netif_list; netif != NULL; netif = netif->next) {
DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
if(ip_addr_isany(&(netif->ip_addr)) ||
ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
(ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
break;
}
}
#if LWIP_DHCP
/* If a DHCP packet has arrived on the interface, we pass it up the
stack regardless of destination IP address. The reason is that
DHCP replies are sent to the IP adress that will be given to this
node (as recommended by RFC 1542 section 3.1.1, referred by RFC
2131). */
if(IPH_PROTO(iphdr) == IP_PROTO_UDP &&
((struct udp_hdr *)((u8_t *)iphdr + IPH_HL(iphdr) * 4/sizeof(u8_t)))->src ==
DHCP_SERVER_PORT) {
netif = inp;
}
#endif /* LWIP_DHCP */
if(netif == NULL) {
/* packet not for us, route or discard */
DEBUGF(IP_DEBUG, ("ip_input: packet not for us.\n"));
// SetCur(1,0);
#ifdef LCD_DEBUG_IP
Put_String("\nIP: not for us");
#endif
#if IP_FORWARD
if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
ip_forward(p, iphdr, inp);
}
#endif /* IP_FORWARD */
pbuf_free(p);
return ERR_OK;
}
// SetCur(1,0);
//Put_String(" ");
#if IP_REASSEMBLY
if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
p = ip_reass(p);
if(p == NULL) {
return ERR_OK;
}
iphdr = p->payload;
}
#else /* IP_REASSEMBLY */
if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
pbuf_free(p);
DEBUGF(IP_DEBUG, ("IP packet dropped since it was fragmented (0x%x).\n",
ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS
++stats.ip.opterr;
++stats.ip.drop;
#endif /* IP_STATS */
return ERR_OK;
}
#endif /* IP_REASSEMBLY */
#if IP_OPTIONS == 0
if(hl * 4 > IP_HLEN) {
DEBUGF(IP_DEBUG, ("IP packet dropped since there were IP options.\n"));
pbuf_free(p);
#ifdef IP_STATS
++stats.ip.opterr;
++stats.ip.drop;
#endif /* IP_STATS */
return ERR_OK;
}
#endif /* IP_OPTIONS == 0 */
/* send to upper layers */
#if IP_DEBUG
DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#endif /* IP_DEBUG */
switch(IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
case IP_PROTO_UDP:
udp_input(p, inp);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
case IP_PROTO_TCP:
/*************************************/
// SetCur(1,0);
// Put_String("\nIP: switch TCP");
/********************************************/
tcp_input(p, inp);
break;
#endif /* LWIP_TCP */
case IP_PROTO_ICMP:
/*************************************/
#ifdef LCD_DEBUG_IP
Put_String("\nIP: switch ICMP");
#endif
/**************************************/
icmp_input(p, inp);
break;
default:
/* send ICMP destination protocol unreachable unless is was a broadcast */
if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
!ip_addr_ismulticast(&(iphdr->dest))) {
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
pbuf_free(p);
DEBUGF(IP_DEBUG, ("Unsupported transportation protocol %d\n", IPH_PROTO(iphdr)));
/*************************************/
#ifdef LCD_DEBUG_IP
Put_String("IP: unsupp. prot\n");
#endif
tcp_input(p, inp);
/********************************************/
#ifdef IP_STATS
++stats.ip.proterr;
++stats.ip.drop;
#endif /* IP_STATS */
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs
* the IP header and calculates the IP header checksum. If the source
* IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
u8_t proto, struct netif *netif)
{
static struct ip_hdr *iphdr;
static u16_t ip_id = 0;
u8_t cnt;
err_t errx;
if(dest != IP_HDRINCL) {
if(pbuf_header(p, IP_HLEN)) {
DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
++stats.ip.err;
#endif /* IP_STATS */
return ERR_BUF;
}
iphdr = p->payload;
/**************************************************************/
/***************************************************************/
IPH_TTL_SET(iphdr, ttl);
IPH_PROTO_SET(iphdr, proto);
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(++ip_id));
if(ip_addr_isany(src)) {
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
} else {
ip_addr_set(&(iphdr->src), src);
}
IPH_CHKSUM_SET(iphdr, 0);
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
} else {
iphdr = p->payload;
dest = &(iphdr->dest);
}
#ifdef IP_STATS
stats.ip.xmit++;
#endif /* IP_STATS */
DEBUGF(IP_DEBUG, ("ip_output_if: %c%c ", netif->name[0], netif->name[1]));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
/**************************************************/
errx=netif->output(netif, p, dest);
return errx;
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
* Simple interface to ip_output_if. It finds the outgoing network
* interface and calls upon ip_output_if to do the actual work.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
{
static struct netif *netif;
if((netif = ip_route(dest)) == NULL) {
DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
#ifdef IP_STATS
++stats.ip.rterr;
#endif /* IP_STATS */
pbuf_free(p);
return ERR_RTE;
}
return ip_output_if(p, src, dest, ttl, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
{
struct ip_hdr *iphdr = p->payload;
u8_t *payload;
payload = (u8_t *)iphdr + IP_HLEN/sizeof(u8_t);
DEBUGF(IP_DEBUG, ("IP header:\n"));
DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
DEBUGF(IP_DEBUG, ("|%2d |%2d | %2d | %4d | (v, hl, tos, len)\n",
IPH_V(iphdr),
IPH_HL(iphdr),
IPH_TOS(iphdr),
ntohs(IPH_LEN(iphdr))));
DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
DEBUGF(IP_DEBUG, ("| %5d |%d%d%d| %4d | (id, flags, offset)\n",
ntohs(IPH_ID(iphdr)),
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
DEBUGF(IP_DEBUG, ("| %2d | %2d | 0x%04x | (ttl, proto, chksum)\n",
IPH_TTL(iphdr),
IPH_PROTO(iphdr),
ntohs(IPH_CHKSUM(iphdr))));
DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
ntohl(iphdr->src.addr) >> 24 & 0xff,
ntohl(iphdr->src.addr) >> 16 & 0xff,
ntohl(iphdr->src.addr) >> 8 & 0xff,
ntohl(iphdr->src.addr) & 0xff));
DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
ntohl(iphdr->dest.addr) >> 24 & 0xff,
ntohl(iphdr->dest.addr) >> 16 & 0xff,
ntohl(iphdr->dest.addr) >> 8 & 0xff,
ntohl(iphdr->dest.addr) & 0xff));
DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -