Esempio n. 1
0
/* 发送一个ICMP差错报文 */
static void
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
{
  struct pbuf *q;
  struct ip_hdr *iphdr;
  /* we can use the echo header here */
	/* 用回显请求的首部描述差错报文首部 */
  struct icmp_echo_hdr *icmphdr;

  /* ICMP header + IP header + 8 bytes of data */
	/* 在IP层申请一个pbuf,会自动预留IP首部和以太网帧首部,
	 * 申请的大小是回显请求首部 + 引起差错的IP数据报首部大小 + IP数据报载荷的前8字节
	 */
  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
                 PBUF_RAM);
  if (q == NULL) {
		/* 申请失败,则返回 */
    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
    return;
  }
  LWIP_ASSERT("check that first pbuf can hold icmp message",
             (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));

	/* 指向引起差错的IP数据报 */
  iphdr = p->payload;
  LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
  LWIP_DEBUGF(ICMP_DEBUG, (" to "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
  LWIP_DEBUGF(ICMP_DEBUG, ("\n"));

	/* 指向ICMP报文首部 */
  icmphdr = q->payload;
	/* 填写类型字段 */
  icmphdr->type = type;
	/* 填写代码字段 */
  icmphdr->code = code;
	/* ICMP首部第4-7字节填0 */
  icmphdr->id = 0;
  icmphdr->seqno = 0;

  /* copy fields from original packet */
	/* 复制引起差错的IP数据报首部+8字节到ICMP数据字段 */
  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
          IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);

  /* calculate checksum */
	/* 计算并填写校验和 */
  icmphdr->chksum = 0;
  icmphdr->chksum = inet_chksum(icmphdr, q->len);
  ICMP_STATS_INC(icmp.xmit);
  /* increase number of messages attempted to send */
  snmp_inc_icmpoutmsgs();
  /* increase number of destination unreachable messages attempted to send */
  snmp_inc_icmpouttimeexcds();
	/* 调用IP层函数输出ICMP报文 */
  ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
	/* 发送完成,释放申请的ICMP用的pbuf */
  pbuf_free(q);
}
Esempio n. 2
0
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
  struct pbuf *q;
  struct ip_hdr *iphdr;
  struct icmp_te_hdr *tehdr;

  q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);

  iphdr = p->payload;
  LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
  LWIP_DEBUGF(ICMP_DEBUG, (" to "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
  LWIP_DEBUGF(ICMP_DEBUG, ("\n"));

  tehdr = q->payload;
  ICMPH_TYPE_SET(tehdr, ICMP_TE);
  ICMPH_CODE_SET(tehdr, t);

  /* copy fields from original packet */
  memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);

  /* calculate checksum */
  tehdr->chksum = 0;
  tehdr->chksum = inet_chksum(tehdr, q->len);
  ICMP_STATS_INC(icmp.xmit);
  /* increase number of messages attempted to send */
  snmp_inc_icmpoutmsgs();
  /* increase number of destination unreachable messages attempted to send */
  snmp_inc_icmpouttimeexcds();
  ip_output(q, NULL, &(iphdr->src),
	    ICMP_TTL, 0, IP_PROTO_ICMP);
  pbuf_free(q);
}
Esempio n. 3
0
static struct netif *
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
  struct netif *netif;

  PERF_START;
  /* Find network interface where to forward this IP packet to. */
  netif = ip_route((struct ip_addr *)&(iphdr->dest));
  if (netif == NULL) {
    LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
                      iphdr->dest.addr));
    snmp_inc_ipnoroutes();
    return (struct netif *)NULL;
  }
  /* Do not forward packets onto the same network interface on which
   * they arrived. */
  if (netif == inp) {
    LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
    snmp_inc_ipnoroutes();
    return (struct netif *)NULL;
  }

  /* decrement TTL */
  IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
  /* send ICMP if TTL == 0 */
  if (IPH_TTL(iphdr) == 0) {
    /* Don't send ICMP messages in response to ICMP messages */
    if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
      icmp_time_exceeded(p, ICMP_TE_TTL);
      snmp_inc_icmpouttimeexcds();
    }
    return (struct netif *)NULL;
  }

  /* Incrementally update the IP checksum. */
  if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
  } else {
    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
  }

  LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
                    iphdr->dest.addr));

  IP_STATS_INC(ip.fw);
  IP_STATS_INC(ip.xmit);
    snmp_inc_ipforwdatagrams();

  PERF_STOP("ip_forward");
  /* transmit pbuf on chosen interface */
  netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
  return netif;
}
Esempio n. 4
0
/**
 * Send an icmp packet in response to an incoming packet.
 *
 * @param p the input packet for which the 'unreachable' should be sent,
 *          p->payload pointing to the IP header
 * @param type Type of the ICMP header
 * @param code Code of the ICMP header
 */
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
{
    struct pbuf *q;
    struct ip_hdr *iphdr;

    /* we can use the echo header here */
    struct icmp_echo_hdr *icmphdr;

    /* ICMP header + IP header + 8 bytes of data */
    q =
      pbuf_alloc(PBUF_IP,
                 sizeof(struct icmp_echo_hdr) + IP_HLEN +
                 ICMP_DEST_UNREACH_DATASIZE, PBUF_RAM);
    if (q == NULL) {
        LWIP_DEBUGF(ICMP_DEBUG,
                    ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
        return;
    }
    LWIP_ASSERT("check that first pbuf can hold icmp message",
                (q->len >=
                 (sizeof(struct icmp_echo_hdr) + IP_HLEN +
                  ICMP_DEST_UNREACH_DATASIZE)));

    iphdr = p->payload;
    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
    ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
    LWIP_DEBUGF(ICMP_DEBUG, (" to "));
    ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
    LWIP_DEBUGF(ICMP_DEBUG, ("\n"));

    icmphdr = q->payload;
    icmphdr->type = type;
    icmphdr->code = code;
    icmphdr->id = 0;
    icmphdr->seqno = 0;

    /* copy fields from original packet */
    SMEMCPY((u8_t *) q->payload + sizeof(struct icmp_echo_hdr),
            (u8_t *) p->payload, IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);

    /* calculate checksum */
    icmphdr->chksum = 0;
    icmphdr->chksum = inet_chksum(icmphdr, q->len);
    ICMP_STATS_INC(icmp.xmit);
    /* increase number of messages attempted to send */
    snmp_inc_icmpoutmsgs();
    /* increase number of destination unreachable messages attempted to send */
    snmp_inc_icmpouttimeexcds();
    ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
    pbuf_free(q);
}
Esempio n. 5
0
/**
 * Send an icmp packet in response to an incoming packet.
 *
 * @param p the input packet for which the 'unreachable' should be sent,
 *          p->payload pointing to the IP header
 * @param type Type of the ICMP header
 * @param code Code of the ICMP header
 */
static void ICACHE_FLASH_ATTR
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
{
  struct pbuf *q;
  struct ip_hdr *iphdr;
  /* we can use the echo header here */
  struct icmp_echo_hdr *icmphdr;
  ip_addr_t iphdr_src;

  /* ICMP header + IP header + 8 bytes of data */
  //为差错报文申请pbuf空间,pbuf中预留IP首部和以太网首部空间,pbuf数据区
  //长度=差错报文首部+差错报文数据长度(IP首部长度+8)
  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
                 PBUF_RAM);
  if (q == NULL) {//失败,返回
    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
    return;
  }
  LWIP_ASSERT("check that first pbuf can hold icmp message",
             (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));

  iphdr = (struct ip_hdr *)p->payload;//指向引起差错的IP数据包首部
  LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
  LWIP_DEBUGF(ICMP_DEBUG, (" to "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
  LWIP_DEBUGF(ICMP_DEBUG, ("\n"));

  icmphdr = (struct icmp_echo_hdr *)q->payload;//指向差错报文首部
  icmphdr->type = type;//填写类型字段
  icmphdr->code = code;//填写代码字段
  icmphdr->id = 0;//对于目的不可达和数据报超时
  icmphdr->seqno = 0;//报文,首部剩余的4个字节都为0

  /* copy fields from original packet 将引起差错的IP数据报的IP首部+8字节数据拷贝到差错报文数据区*/
  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
          IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);

  /* calculate checksum */
  icmphdr->chksum = 0;//报文校验和字段清0
  icmphdr->chksum = inet_chksum(icmphdr, q->len);//计算填写校验和
  ICMP_STATS_INC(icmp.xmit);
  /* increase number of messages attempted to send */
  snmp_inc_icmpoutmsgs();
  /* increase number of destination unreachable messages attempted to send */
  snmp_inc_icmpouttimeexcds();
  ip_addr_copy(iphdr_src, iphdr->src);
  ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP);//调用IP层函数输出ICMP报文
  pbuf_free(q);
}
Esempio n. 6
0
/**
 * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
 *
 * @param p the input packet for which the 'time exceeded' should be sent,
 *          p->payload pointing to the IP header
 * @param t type of the 'time exceeded' packet
 */
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
  struct pbuf *q;
  struct ip_hdr *iphdr;
  struct icmp_te_hdr *tehdr;

  /* ICMP header + IP header + 8 bytes of data */
  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
                 PBUF_RAM);
  if (q == NULL) {
    LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
    return;
  }
  LWIP_ASSERT("check that first pbuf can hold icmp message",
             (q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));

  iphdr = (struct ip_hdr *) p->payload;
  LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
  LWIP_DEBUGF(ICMP_DEBUG, (" to "));
  ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
  LWIP_DEBUGF(ICMP_DEBUG, ("\n"));

  tehdr = (struct icmp_te_hdr *) q->payload;
  ICMPH_TYPE_SET(tehdr, ICMP_TE);
  ICMPH_CODE_SET(tehdr, t);

  /* copy fields from original packet */
  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), (u8_t *)p->payload,
          IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);

  /* calculate checksum */
  tehdr->chksum = 0;
  tehdr->chksum = inet_chksum(tehdr, q->len);
  ICMP_STATS_INC(icmp.xmit);
  /* increase number of messages attempted to send */
  snmp_inc_icmpoutmsgs();
  /* increase number of destination unreachable messages attempted to send */
  snmp_inc_icmpouttimeexcds();
  ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
  pbuf_free(q);
}