/** * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * * @param netif network interface on which create the IP-Address * @param ipaddr ip address to initialize */ static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr) { /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * compliant to RFC 3927 Section 2.1 * We have 254 * 256 possibilities */ u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); addr += netif->autoip->tried_llipaddr; addr = AUTOIP_NET | (addr & 0xffff); /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ if (addr < AUTOIP_RANGE_START) { addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; } if (addr > AUTOIP_RANGE_END) { addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; } LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && (addr <= AUTOIP_RANGE_END)); ip4_addr_set_u32(ipaddr, htonl(addr)); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); }
/** * Change the IP address of a network interface * * @param netif the network interface to change * @param ipaddr the new IP address * * @note call netif_set_addr() if you also want to change netmask and * default gateway */ void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) { /* TODO: Handling of obsolete pcbs */ /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ #if LWIP_TCP struct tcp_pcb *pcb; struct tcp_pcb_listen *lpcb; /* address is actually being changed? */ if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); pcb = tcp_active_pcbs; while (pcb != NULL) { /* PCB bound to current local interface address? */ if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr)) #if LWIP_AUTOIP /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ && !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip)) #endif /* LWIP_AUTOIP */ ) { /* this connection must be aborted */ struct tcp_pcb *next = pcb->next; LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %pp\n", (void *)pcb)); tcp_abort(pcb); pcb = next; } else { pcb = pcb->next; } } for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { /* PCB bound to current local interface address? */ if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) && (ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) { /* The PCB is listening to the old ipaddr and * is set to listen to the new one instead */ ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr); } } } #endif snmp_delete_ipaddridx_tree(netif); snmp_delete_iprteidx_tree(0,netif); /* set new IP address to netif */ ip_addr_set(&(netif->ip_addr), ipaddr); snmp_insert_ipaddridx_tree(netif); snmp_insert_iprteidx_tree(0,netif); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ((netif->name[0]) ?netif->name[0] :'-'), ((netif->name[1]) ?netif->name[1] :'-'), ip4_addr1_16(&netif->ip_addr), ip4_addr2_16(&netif->ip_addr), ip4_addr3_16(&netif->ip_addr), ip4_addr4_16(&netif->ip_addr))); }
/****************************************************************************** * FunctionName : espconn_tcp_accept * Description : A new incoming connection has been accepted. * Parameters : arg -- Additional argument to pass to the callback function * pcb -- The connection pcb which is accepted * err -- An unused error code, always ERR_OK currently * Returns : acception result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct espconn *espconn = arg; espconn_msg *paccept = NULL; remot_info *pinfo = NULL; LWIP_UNUSED_ARG(err); if(system_get_free_heap_size() < 8192) return ERR_MEM; // added PV` paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); tcp_arg(pcb, paccept); tcp_err(pcb, esponn_server_err); if (paccept == NULL) return ERR_MEM; /*insert the node to the active connection list*/ espconn_list_creat(&plink_active, paccept); paccept->preverse = espconn; paccept->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn)); if (paccept->pespconn == NULL) return ERR_MEM; paccept->pespconn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); if (paccept->pespconn->proto.tcp == NULL) return ERR_MEM; //paccept->pcommon.timeout = 0x0a; //link_timer = 0x0a; paccept->pcommon.pcb = pcb; paccept->pcommon.remote_port = pcb->remote_port; paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip); paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip); os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); espconn->proto.tcp->remote_port = pcb->remote_port; espconn->state = ESPCONN_CONNECT; espconn_copy_partial(paccept->pespconn, espconn); espconn_get_connection_info(espconn, &pinfo , 0); espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn) + 1) return ERR_ISCONN; tcp_sent(pcb, espconn_server_sent); tcp_recv(pcb, espconn_server_recv); tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ if (paccept->pespconn->proto.tcp->connect_callback != NULL) { paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); } return ERR_OK; }
/** * Change the default gateway for a network interface * * @param netif the network interface to change * @param gw the new default gateway * * @note call netif_set_addr() if you also want to change ip address and netmask */ void netif_set_gw(struct netif *netif, ip_addr_t *gw) { ip_addr_set(&(netif->gw), gw); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], ip4_addr1_16(&netif->gw), ip4_addr2_16(&netif->gw), ip4_addr3_16(&netif->gw), ip4_addr4_16(&netif->gw))); }
/** * Change the default gateway for a network interface * * @param netif the network interface to change * @param gw the new default gateway * * @note call netif_set_addr() if you also want to change ip address and netmask */ void netif_set_gw(struct netif *netif, const ip4_addr_t *gw) { ip4_addr_set(ip_2_ip4(&netif->gw), gw); IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], ip4_addr1_16(netif_ip4_gw(netif)), ip4_addr2_16(netif_ip4_gw(netif)), ip4_addr3_16(netif_ip4_gw(netif)), ip4_addr4_16(netif_ip4_gw(netif)))); }
static void show_ip_pkt(struct pbuf *p) { struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; u8_t *payload; payload = (u8_t *)iphdr + IP_HLEN; _hx_printf("[%s]IP header:\r\n",__func__); _hx_printf("+-------------------------------+\r\n"); _hx_printf("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\r\n", IPH_V(iphdr), IPH_HL(iphdr), IPH_TOS(iphdr), ntohs(IPH_LEN(iphdr))); _hx_printf("+-------------------------------+\r\n"); _hx_printf("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\r\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); _hx_printf("+-------------------------------+\r\n"); _hx_printf("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\r\n", IPH_TTL(iphdr), IPH_PROTO(iphdr), ntohs(IPH_CHKSUM(iphdr))); _hx_printf("+-------------------------------+\r\n"); _hx_printf("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\r\n", ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src), ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src)); _hx_printf("+-------------------------------+\r\n"); _hx_printf("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\r\n", ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest), ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest)); _hx_printf("+-------------------------------+\r\n"); }
/** * Change the netmask of a network interface * * @param netif the network interface to change * @param netmask the new netmask * * @note call netif_set_addr() if you also want to change ip address and * default gateway */ void netif_set_netmask(struct netif *netif, ip_addr_t *netmask) { snmp_delete_iprteidx_tree(0, netif); /* set new netmask to netif */ ip_addr_set(&(netif->netmask), netmask); snmp_insert_iprteidx_tree(0, netif); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], ip4_addr1_16(&netif->netmask), ip4_addr2_16(&netif->netmask), ip4_addr3_16(&netif->netmask), ip4_addr4_16(&netif->netmask))); }
/** * Change the netmask of a network interface * * @param netif the network interface to change * @param netmask the new netmask * * @note call netif_set_addr() if you also want to change ip address and * default gateway */ void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) { mib2_remove_route_ip4(0, netif); /* set new netmask to netif */ ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); mib2_add_route_ip4(0, netif); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], ip4_addr1_16(netif_ip4_netmask(netif)), ip4_addr2_16(netif_ip4_netmask(netif)), ip4_addr3_16(netif_ip4_netmask(netif)), ip4_addr4_16(netif_ip4_netmask(netif)))); }
/** Add a new static entry to the ARP table. If an entry exists for the * specified IP address, this entry is overwritten. * If packets are queued for the specified IP address, they are sent out. * * @param ipaddr IP address for the new static entry * @param ethaddr ethernet address for the new static entry * @return @see return values of etharp_add_static_entry */ err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) { struct netif *netif; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); netif = ip_route(ipaddr); if (netif == NULL) { return ERR_RTE; } return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); }
/** * Change the IP address of a network interface * * @param netif the network interface to change * @param ipaddr the new IP address * * @note call netif_set_addr() if you also want to change netmask and * default gateway */ void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) { ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY); #if ESP_LWIP ip4_addr_t *last_addr = ip_2_ip4(&netif->last_ip_addr); #else ip4_addr_t *last_addr = netif_ip4_addr(netif); #endif /* address is actually being changed? */ if (ip4_addr_cmp(&new_addr, netif_ip4_addr(netif)) == 0) { LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); #if LWIP_TCP tcp_netif_ipv4_addr_changed(last_addr, ipaddr); #endif /* LWIP_TCP */ #if LWIP_UDP udp_netif_ipv4_addr_changed(last_addr, ipaddr); #endif /* LWIP_UDP */ mib2_remove_ip4(netif); mib2_remove_route_ip4(0, netif); /* set new IP address to netif */ ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); mib2_add_ip4(netif); mib2_add_route_ip4(0, netif); netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); NETIF_STATUS_CALLBACK(netif); } LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], ip4_addr1_16(netif_ip4_addr(netif)), ip4_addr2_16(netif_ip4_addr(netif)), ip4_addr3_16(netif_ip4_addr(netif)), ip4_addr4_16(netif_ip4_addr(netif)))); if (ipaddr && !ip4_addr_isany(ipaddr)) { ip4_addr_set(ip_2_ip4(&netif->last_ip_addr), ipaddr); } }
/****************************************************************************** * FunctionName : espconn_client_connect * Description : A new incoming connection has been connected. * Parameters : arg -- Additional argument to pass to the callback function * tpcb -- The connection pcb which is connected * err -- An unused error code, always ERR_OK currently * Returns : connection result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err) { espconn_msg *pcon = arg; espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb); if (err == ERR_OK){ /*Reserve the remote information for current active connection*/ pcon->pespconn->state = ESPCONN_CONNECT; pcon->pcommon.err = err; pcon->pcommon.pcb = tpcb; pcon->pcommon.local_port = tpcb->local_port; pcon->pcommon.local_ip = tpcb->local_ip.u_addr.ip4.addr; pcon->pcommon.remote_port = tpcb->remote_port; pcon->pcommon.remote_ip[0] = ip4_addr1_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.remote_ip[1] = ip4_addr2_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.remote_ip[2] = ip4_addr3_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.remote_ip[3] = ip4_addr4_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.write_flag = true; tcp_arg(tpcb, (void *) pcon); /*Set the specify function that should be called * when TCP data has been successfully delivered, * when active connection receives data*/ tcp_sent(tpcb, espconn_client_sent); tcp_recv(tpcb, espconn_client_recv); /*Disable Nagle algorithm default*/ tcp_nagle_disable(tpcb); /*Default set the total number of espconn_buf on the unsent lists for one*/ espconn_tcp_set_buf_count(pcon->pespconn, 1); if (pcon->pespconn->proto.tcp->connect_callback != NULL) { pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn); } /*Enable keep alive option*/ if (espconn_keepalive_disabled(pcon)) espconn_keepalive_enable(tpcb); } else{ printf("err in host connected (%s)\n",lwip_strerr(err)); } return err; }
/** * Change the netmask of a network interface * * @param netif the network interface to change * @param netmask the new netmask * * @note call if_set_addr() if you also want to change ip address and * default gateway */ void if_set_netmask (struct interface *netif, ip_addr_t * netmask) { #ifdef CONFIG_OPENSWITCH_TCP_IP snmp_delete_iprteidx_tree (0, netif); #endif /* set new netmask to netif */ ip_addr_set (&(netif->netmask), netmask); #ifdef CONFIG_OPENSWITCH_TCP_IP snmp_insert_iprteidx_tree (0, netif); #endif LWIP_DEBUGF (NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %" U16_F ".%" U16_F ".%" U16_F ".%" U16_F "\n", netif->ifDescr[0], netif->ifDescr[1], ip4_addr1_16 (&netif->netmask), ip4_addr2_16 (&netif->netmask), ip4_addr3_16 (&netif->netmask), ip4_addr4_16 (&netif->netmask))); }
/** * Send keepalive packets to keep a connection active although * no data is sent over it. * * Called by tcp_slowtmr() * * @param pcb the tcp_pcb for which to send a keepalive packet */ void tcp_keepalive(struct tcp_pcb *pcb) { struct pbuf *p; struct tcp_hdr *tcphdr; LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); if(p == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n")); return; } tcphdr = (struct tcp_hdr *)p->payload; #if CHECKSUM_GEN_TCP tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, (u16_t)p->tot_len); #endif TCP_STATS_INC(tcp.xmit); /* Send output to IP */ #if LWIP_NETIF_HWADDRHINT ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, &(pcb->addr_hint)); #elif LWIP_3RD_PARTY_L3 pcb->ip_output(p, pcb, 0); #else /* LWIP_NETIF_HWADDRHINT*/ ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); #endif /* LWIP_NETIF_HWADDRHINT*/ tcp_tx_pbuf_free(pcb, p); LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt)); (void)tcphdr; /* Fix warning -Wunused-but-set-variable*/ }
/** * Configure interface for use with current LL IP-Address * * @param netif network interface to configure with current LL IP-Address */ static err_t autoip_bind(struct netif *netif) { struct autoip *autoip = netif->autoip; ip4_addr_t sn_mask, gw_addr; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); IP4_ADDR(&sn_mask, 255, 255, 0, 0); IP4_ADDR(&gw_addr, 0, 0, 0, 0); netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); /* interface is used by routing now that an address is set */ return ERR_OK; }
/** Remove a static entry from the ARP table previously added with a call to * etharp_add_static_entry. * * @param ipaddr IP address of the static entry to remove * @return ERR_OK: entry removed * ERR_MEM: entry wasn't found * ERR_ARG: entry wasn't a static entry but a dynamic one */ err_t etharp_remove_static_entry(ip_addr_t *ipaddr) { s8_t i; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); /* find or create ARP entry */ i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } if ((arp_table[i].state != ETHARP_STATE_STABLE) || (arp_table[i].static_entry == 0)) { /* entry wasn't a static entry, cannot remove it */ return ERR_ARG; } /* entry found, free it */ free_entry(i); return ERR_OK; }
/** * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * * @param netif network interface on which create the IP-Address * @param ipaddr ip address to initialize */ static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr) { /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * compliant to RFC 3927 Section 2.1 * We have 254 * 256 possibilities */ u32_t addr; if (prev_llipaddr.addr) { /* Use previously announced IP address, if any. * Previously announced IP doesn't persist across device reboot. * Its useful only in case of network hot-plugging/link-loss. */ addr = ntohl(prev_llipaddr.addr); } else { addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); } addr += netif->autoip->tried_llipaddr; addr = AUTOIP_NET | (addr & 0xffff); /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ if (addr < AUTOIP_RANGE_START) { addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; } if (addr > AUTOIP_RANGE_END) { addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; } LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && (addr <= AUTOIP_RANGE_END)); ip4_addr_set_u32(ipaddr, htonl(addr)); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); }
/** * Configure interface for use with current LL IP-Address * * @param netif network interface to configure with current LL IP-Address */ static err_t autoip_bind(struct netif *netif) { struct autoip *autoip = netif->autoip; ip_addr_t sn_mask, gw_addr; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); IP4_ADDR(&sn_mask, 255, 255, 0, 0); IP4_ADDR(&gw_addr, 0, 0, 0, 0); netif_set_ipaddr(netif, &autoip->llipaddr); netif_set_netmask(netif, &sn_mask); netif_set_gw(netif, &gw_addr); /* bring the interface up */ netif_set_up(netif); return ERR_OK; }
/****************************************************************************** * FunctionName : espconn_udp_server_recv * Description : This callback will be called when receiving a datagram. * Parameters : arg -- user supplied argument * upcb -- the udp_pcb which received data * p -- the packet buffer that was received * addr -- the remote IP address from which the packet was received * port -- the remote port from which the packet was received * Returns : none *******************************************************************************/ static void ICACHE_FLASH_ATTR espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { espconn_msg *precv = arg; struct pbuf *q = NULL; u8_t *pdata = NULL; u16_t length = 0; struct ip_info ipconfig; LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb)); upcb->remote_port = port; upcb->remote_ip = *addr; precv->pcommon.remote_ip[0] = ip4_addr1_16(&upcb->remote_ip); precv->pcommon.remote_ip[1] = ip4_addr2_16(&upcb->remote_ip); precv->pcommon.remote_ip[2] = ip4_addr3_16(&upcb->remote_ip); precv->pcommon.remote_ip[3] = ip4_addr4_16(&upcb->remote_ip); os_memcpy(precv->pespconn->proto.udp->remote_ip, precv->pcommon.remote_ip, 4); precv->pespconn->proto.udp->remote_port = port; precv->pcommon.remote_port = port; precv->pcommon.pcb = upcb; if (wifi_get_opmode() != 1) { wifi_get_ip_info(1, &ipconfig); if (!ip_addr_netcmp((struct ip_addr *)precv->pespconn->proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) { wifi_get_ip_info(0, &ipconfig); } } else { wifi_get_ip_info(0, &ipconfig); } upcb->local_ip = ipconfig.ip; precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&upcb->local_ip); precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&upcb->local_ip); precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&upcb->local_ip); precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&upcb->local_ip); if (p != NULL) { // q = p; // while (q != NULL) { // pdata = (u8_t *)os_zalloc(q ->len + 1); // length = pbuf_copy_partial(q, pdata, q ->len, 0); // // LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %x\n", __LINE__, length)); // precv->pcommon.pcb = upcb; // // if (length != 0) { // if (precv->pespconn->recv_callback != NULL) { // precv->pespconn->recv_callback(precv->pespconn, pdata, length); // } // } // // q = q->next; // os_free(pdata); // } pdata = (u8_t *)os_zalloc(p ->tot_len + 1); length = pbuf_copy_partial(p, pdata, p ->tot_len, 0); precv->pcommon.pcb = upcb; pbuf_free(p); if (length != 0) { if (precv->pespconn->recv_callback != NULL) { precv->pespconn->recv_callback(precv->pespconn, pdata, length); } } os_free(pdata); } else { return; } }
/** * Update (or insert) a IP/MAC address pair in the ARP cache. * * If a pending entry is resolved, any queued packets will be sent * at this point. * * @param netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. * @param flags @see definition of ETHARP_FLAG_* * * @return * - ERR_OK Succesfully updated ARP cache. * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */ static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); /* non-unicast address? */ if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif) || ip_addr_ismulticast(ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n")); return ERR_ARG; } /* find or create ARP entry */ i = find_entry(ipaddr, flags); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } #if ETHARP_SUPPORT_STATIC_ENTRIES if (flags & ETHARP_FLAG_STATIC_ENTRY) { /* record static type */ arp_table[i].static_entry = 1; } #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; #if LWIP_SNMP /* record network interface */ arp_table[i].netif = netif; #endif /* LWIP_SNMP */ /* insert in SNMP ARP index tree */ snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); /* update address */ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; #if ARP_QUEUEING /* this is where we will send out queued packets! */ while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ struct etharp_q_entry *q = arp_table[i].q; /* pop first item off the queue */ arp_table[i].q = q->next; /* get the packet pointer */ p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } #endif /* ARP_QUEUEING */ return ERR_OK; }
/** * Update (or insert) a IP/MAC address pair in the ARP cache. * * If a pending entry is resolved, any queued packets will be sent * at this point. * * @param netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. * @param flags See @ref etharp_state * * @return * - ERR_OK Successfully updated ARP cache. * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */ static err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); /* non-unicast address? */ if (ip4_addr_isany(ipaddr) || ip4_addr_isbroadcast(ipaddr, netif) || ip4_addr_ismulticast(ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); return ERR_ARG; } /* find or create ARP entry */ i = etharp_find_entry(ipaddr, flags, netif); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } #if ETHARP_SUPPORT_STATIC_ENTRIES if (flags & ETHARP_FLAG_STATIC_ENTRY) { /* record static type */ arp_table[i].state = ETHARP_STATE_STATIC; } else if (arp_table[i].state == ETHARP_STATE_STATIC) { /* found entry is a static type, don't overwrite it */ return ERR_VAL; } else #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ { /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; } /* record network interface */ arp_table[i].netif = netif; /* insert in SNMP ARP index tree */ mib2_add_arp_entry(netif, &arp_table[i].ipaddr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); /* update address */ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; /* this is where we will send out queued packets! */ #if ARP_QUEUEING while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ struct etharp_q_entry *q = arp_table[i].q; /* pop first item off the queue */ arp_table[i].q = q->next; /* get the packet pointer */ p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); #else /* ARP_QUEUEING */ if (arp_table[i].q != NULL) { struct pbuf *p = arp_table[i].q; arp_table[i].q = NULL; #endif /* ARP_QUEUEING */ /* send the queued IP packet */ ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP); /* free the queued IP packet */ pbuf_free(p); } return ERR_OK; } #if ETHARP_SUPPORT_STATIC_ENTRIES /** Add a new static entry to the ARP table. If an entry exists for the * specified IP address, this entry is overwritten. * If packets are queued for the specified IP address, they are sent out. * * @param ipaddr IP address for the new static entry * @param ethaddr ethernet address for the new static entry * @return See return values of etharp_add_static_entry */ err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) { struct netif *netif; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); netif = ip4_route(ipaddr); if (netif == NULL) { return ERR_RTE; } return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); } /** Remove a static entry from the ARP table previously added with a call to * etharp_add_static_entry. * * @param ipaddr IP address of the static entry to remove * @return ERR_OK: entry removed * ERR_MEM: entry wasn't found * ERR_ARG: entry wasn't a static entry but a dynamic one */ err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr) { s8_t i; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); /* find or create ARP entry */ i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } if (arp_table[i].state != ETHARP_STATE_STATIC) { /* entry wasn't a static entry, cannot remove it */ return ERR_ARG; } /* entry found, free it */ etharp_free_entry(i); return ERR_OK; }
/** * Send persist timer zero-window probes to keep a connection active * when a window update is lost. * * Called by tcp_slowtmr() * * @param pcb the tcp_pcb for which to send a zero-window probe packet */ void tcp_zero_window_probe(struct tcp_pcb *pcb) { struct pbuf *p; struct tcp_hdr *tcphdr; struct tcp_seg *seg; u16_t len; u8_t is_fin; LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to %" U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: tcp_ticks %"U32_F " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); seg = pcb->unacked; if(seg == NULL) { seg = pcb->unsent; } if(seg == NULL) { return; } is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); /* we want to send one seqno: either FIN or data (no options) */ len = is_fin ? 0 : 1; p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); if(p == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); return; } tcphdr = (struct tcp_hdr *)p->payload; if (is_fin) { /* FIN segment, no data */ TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); } else { /* Data segment, copy in one byte from the head of the unacked queue */ *((char *)p->payload + TCP_HLEN) = *(char *)seg->dataptr; } #if CHECKSUM_GEN_TCP tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, (u16_t)p->tot_len); #endif TCP_STATS_INC(tcp.xmit); /* Send output to IP */ #if LWIP_NETIF_HWADDRHINT ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, &(pcb->addr_hint)); #elif LWIP_3RD_PARTY_L3 pcb->ip_output(p, pcb, 0); #else /* LWIP_NETIF_HWADDRHINT*/ ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); #endif /* LWIP_NETIF_HWADDRHINT*/ tcp_tx_pbuf_free(pcb, p); LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F " ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt)); }
/****************************************************************************** * FunctionName : espconn_tcp_accept * Description : A new incoming connection has been accepted. * Parameters : arg -- Additional argument to pass to the callback function * pcb -- The connection pcb which is accepted * err -- An unused error code, always ERR_OK currently * Returns : acception result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct espconn *espconn = arg; espconn_msg *paccept = NULL; remot_info *pinfo = NULL; LWIP_UNUSED_ARG(err); if (!espconn || !espconn->proto.tcp) { return ERR_ARG; } tcp_arg(pcb, paccept); tcp_err(pcb, esponn_server_err); /*Ensure the active connection is less than the count of active connections on the server*/ espconn_get_connection_info(espconn, &pinfo , 0); espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn)) return ERR_ISCONN; /*Creates a new active connect control message*/ paccept = (espconn_msg *)malloc(sizeof(espconn_msg)); memset(paccept, 0, sizeof(espconn_msg)); tcp_arg(pcb, paccept); if (paccept == NULL) return ERR_MEM; /*Insert the node to the active connection list*/ espconn_list_creat(&plink_active, paccept); paccept->preverse = espconn; paccept->pespconn = (struct espconn *)malloc(sizeof(struct espconn)); if (paccept->pespconn == NULL) return ERR_MEM; paccept->pespconn->proto.tcp = (esp_tcp *)malloc(sizeof(esp_tcp)); if (paccept->pespconn->proto.tcp == NULL) return ERR_MEM; /*Reserve the remote information for current active connection*/ paccept->pcommon.pcb = pcb; paccept->pcommon.remote_port = pcb->remote_port; paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.write_flag = true; memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); espconn->proto.tcp->remote_port = pcb->remote_port; espconn->state = ESPCONN_CONNECT; espconn_copy_partial(paccept->pespconn, espconn); /*Set the specify function that should be called * when TCP data has been successfully delivered, * when active connection receives data, * or periodically from active connection*/ tcp_sent(pcb, espconn_server_sent); tcp_recv(pcb, espconn_server_recv); tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ /*Disable Nagle algorithm default*/ tcp_nagle_disable(pcb); /*Default set the total number of espconn_buf on the unsent lists for one*/ espconn_tcp_set_buf_count(paccept->pespconn, 1); if (paccept->pespconn->proto.tcp->connect_callback != NULL) { paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); } /*Enable keep alive option*/ if (espconn_keepalive_disabled(paccept)) espconn_keepalive_enable(pcb); return ERR_OK; }
static void ICACHE_FLASH_ATTR dnsQueryReceived(void *arg, char *data, unsigned short length) { // parse incoming query domain char domain[30]; char *writePos=domain; memset(domain,0,30); int offSet=12; int len=data[offSet]; while(len!=0 && offSet<length) { offSet++; memcpy(writePos,data+offSet,len); writePos+=len; //advance offSet+=len; len=data[offSet]; if(len!=0) { *writePos='.'; writePos++; } } DNS_DBG("DNS Query Received: %s",domain); if(!isKnownDNS(domain)) return; struct espconn *conn=arg; remot_info *premot = NULL; if (espconn_get_connection_info(conn,&premot,0) == ESPCONN_OK) { os_memcpy(conn->proto.udp->remote_ip, premot->remote_ip, 4); conn->proto.udp->remote_port = premot->remote_port; uint8_t *ip1 = conn->proto.udp->remote_ip; NODE_DBG("UDP:\nremote_ip: %d.%d.%d.%d remote_port: %d\n",ip4_addr1_16(ip1),ip4_addr2_16(ip1), ip4_addr3_16(ip1), ip4_addr4_16(ip1), premot->remote_port); } else { NODE_ERR("UDP: connection_info == NULL?\n"); } //build response char response[100] = {data[0], data[1], 0b10000100 | (0b00000001 & data[2]), //response, authorative answer, not truncated, copy the recursion bit 0b00000000, //no recursion available, no errors data[4], data[5], //Question count data[4], data[5], //answer count 0x00, 0x00, //NS record count 0x00, 0x00}; //Resource record count int idx = 12; memcpy(response+12, data+12, length-12); //Copy the rest of the query section idx += length-12; //Set a pointer to the domain name in the question section response[idx] = 0xC0; response[idx+1] = 0x0C; //Set the type to "Host Address" response[idx+2] = 0x00; response[idx+3] = 0x01; //Set the response class to IN response[idx+4] = 0x00; response[idx+5] = 0x01; //A 32 bit integer specifying TTL in seconds, 0 means no caching response[idx+6] = 0x00; response[idx+7] = 0x00; response[idx+8] = 0x00; response[idx+9] = 0x00; //RDATA length response[idx+10] = 0x00; response[idx+11] = 0x04; //4 byte IP address //The IP address response[idx + 12] = 192; response[idx + 13] = 168; response[idx + 14] = 4; response[idx + 15] = 1; int ret = espconn_send(conn, (uint8_t*)response, idx+16); uint8_t *ip = conn->proto.udp->local_ip; NODE_DBG("local_ip: %d.%d.%d.%d local_port: %d\n",ip4_addr1_16(ip),ip4_addr2_16(ip), ip4_addr3_16(ip), ip4_addr4_16(ip),conn->proto.udp->local_port); NODE_DBG("DNS reply sent\n"); }
/** * Send the raw IP packet to the given address. Note that actually you cannot * modify the IP headers (this is inconsistent with the receive callback where * you actually get the IP headers), you can only specify the IP payload here. * It requires some more changes in lwIP. (there will be a raw_send() function * then.) * * @param pcb the raw pcb which to send * @param p the IP payload to send * @param ipaddr the destination address of the IP packet * */ err_t raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) { err_t err; struct netif *netif; ip_addr_t *src_ip; struct pbuf *q; /* q will be sent down the stack */ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); /* not enough space to add an IP header to first pbuf in given p chain? */ if (pbuf_header(p, IP_HLEN)) { /* allocate header in new pbuf */ q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); /* new header pbuf could not be allocated? */ if (q == NULL) { LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); return ERR_MEM; } /* chain header q in front of given pbuf p */ pbuf_chain(q, p); /* { first pbuf q points to header pbuf } */ LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); } else { /* first pbuf q equals given pbuf */ q = p; if(pbuf_header(q, -IP_HLEN)) { LWIP_ASSERT("Can't restore header we just removed!", 0); return ERR_MEM; } } if ((netif = ip_route(ipaddr)) == NULL) { LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); /* free any temporary header pbuf allocated by pbuf_header() */ if (q != p) { pbuf_free(q); } return ERR_RTE; } #if IP_SOF_BROADCAST /* broadcast filter? */ if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) { LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); /* free any temporary header pbuf allocated by pbuf_header() */ if (q != p) { pbuf_free(q); } return ERR_VAL; } #endif /* IP_SOF_BROADCAST */ if (ip_addr_isany(&pcb->local_ip)) { /* use outgoing network interface IP address as source address */ src_ip = &(netif->ip_addr); } else { /* use RAW PCB local IP address as source address */ src_ip = &(pcb->local_ip); } #if LWIP_NETIF_HWADDRHINT netif->addr_hint = &(pcb->addr_hint); #endif /* LWIP_NETIF_HWADDRHINT*/ err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); #if LWIP_NETIF_HWADDRHINT netif->addr_hint = NULL; #endif /* LWIP_NETIF_HWADDRHINT*/ /* did we chain a header earlier? */ if (q != p) { /* free the header */ pbuf_free(q); } return err; }
/** * Process an incoming UDP datagram. * * Given an incoming UDP datagram (as a chain of pbufs) this function * finds a corresponding UDP PCB and hands over the pbuf to the pcbs * recv function. If no pcb is found or the datagram is incorrect, the * pbuf is freed. * * @param p pbuf to be demultiplexed to a UDP PCB. * @param inp network interface on which the datagram was received. * */ void udp_input(struct pbuf *p, struct netif *inp) { struct udp_hdr *udphdr; struct udp_pcb *pcb, *prev; struct udp_pcb *uncon_pcb; struct ip_hdr *iphdr; u16_t src, dest; u8_t local_match; u8_t broadcast; PERF_START; UDP_STATS_INC(udp.recv); iphdr = (struct ip_hdr *)p->payload; /* Check minimum length (IP header + UDP header) * and move payload pointer to UDP header */ if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) { /* drop short packets */ LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); UDP_STATS_INC(udp.lenerr); UDP_STATS_INC(udp.drop); snmp_inc_udpinerrors(); pbuf_free(p); goto end; } udphdr = (struct udp_hdr *)p->payload; /* is broadcast packet ? */ broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp); LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); /* convert src and dest ports to host byte order */ src = ntohs(udphdr->src); dest = ntohs(udphdr->dest); udp_debug_print(udphdr); /* print the UDP source and destination */ LWIP_DEBUGF(UDP_DEBUG, ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- " "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest), ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest), ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src), ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src))); #if LWIP_DHCP pcb = NULL; /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ if (dest == DHCP_CLIENT_PORT) { /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ if (src == DHCP_SERVER_PORT) { if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { /* accept the packe if (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! - inp->dhcp->pcb->remote == ANY or iphdr->src */ if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) || ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) { pcb = inp->dhcp->pcb; } } } } else #endif /* LWIP_DHCP */ { prev = NULL; local_match = 0; uncon_pcb = NULL; /* Iterate through the UDP pcb list for a matching pcb. * 'Perfect match' pcbs (connected to the remote port & ip address) are * preferred. If no perfect match is found, the first unconnected pcb that * matches the local port and ip address gets the datagram. */ for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { local_match = 0; /* print the PCB local and remote address */ LWIP_DEBUGF(UDP_DEBUG, ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- " "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port, ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port)); /* compare PCB local addr+port to UDP destination addr+port */ if (pcb->local_port == dest) { if ( (!broadcast && ip_addr_isany(&pcb->local_ip)) || ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) || #if LWIP_IGMP ip_addr_ismulticast(¤t_iphdr_dest) || #endif /* LWIP_IGMP */ #if IP_SOF_BROADCAST_RECV (broadcast && ip_get_option(pcb, SOF_BROADCAST) && (ip_addr_isany(&pcb->local_ip) || ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { #else /* IP_SOF_BROADCAST_RECV */ (broadcast && (ip_addr_isany(&pcb->local_ip) || ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { #endif /* IP_SOF_BROADCAST_RECV */ local_match = 1; if ((uncon_pcb == NULL) && ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { /* the first unconnected matching PCB */ uncon_pcb = pcb; } } } /* compare PCB remote addr+port to UDP source addr+port */ if ((local_match != 0) && (pcb->remote_port == src) && (ip_addr_isany(&pcb->remote_ip) || ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) { /* the first fully matching PCB */ if (prev != NULL) { /* move the pcb to the front of udp_pcbs so that is found faster next time */ prev->next = pcb->next; pcb->next = udp_pcbs; udp_pcbs = pcb; } else { UDP_STATS_INC(udp.cachehit); } break; } prev = pcb; } /* no fully matching pcb found? then look for an unconnected pcb */ if (pcb == NULL) { pcb = uncon_pcb; } } /* Check checksum if this is a match or if it was directed at us. */ if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) { LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); #if LWIP_UDPLITE if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) { /* Do the UDP Lite checksum */ #if CHECKSUM_CHECK_UDP u16_t chklen = ntohs(udphdr->len); if (chklen < sizeof(struct udp_hdr)) { if (chklen == 0) { /* For UDP-Lite, checksum length of 0 means checksum over the complete packet (See RFC 3828 chap. 3.1) */ chklen = p->tot_len; } else { /* At least the UDP-Lite header must be covered by the checksum! (Again, see RFC 3828 chap. 3.1) */ UDP_STATS_INC(udp.chkerr); UDP_STATS_INC(udp.drop); snmp_inc_udpinerrors(); pbuf_free(p); goto end; } } if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest, IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) { LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); UDP_STATS_INC(udp.chkerr); UDP_STATS_INC(udp.drop); snmp_inc_udpinerrors(); pbuf_free(p); goto end; } #endif /* CHECKSUM_CHECK_UDP */ } else #endif /* LWIP_UDPLITE */ { #if CHECKSUM_CHECK_UDP if (udphdr->chksum != 0) { if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), IP_PROTO_UDP, p->tot_len) != 0) { LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_input: UDP datagram discarded due to failing checksum\n")); UDP_STATS_INC(udp.chkerr); UDP_STATS_INC(udp.drop); snmp_inc_udpinerrors(); pbuf_free(p); goto end; } } #endif /* CHECKSUM_CHECK_UDP */ } if(pbuf_header(p, -UDP_HLEN)) { /* Can we cope with this failing? Just assert for now */ LWIP_ASSERT("pbuf_header failed\n", 0); UDP_STATS_INC(udp.drop); snmp_inc_udpinerrors(); pbuf_free(p); goto end; } if (pcb != NULL) { snmp_inc_udpindatagrams(); #if SO_REUSE && SO_REUSE_RXTOALL if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) && ip_get_option(pcb, SOF_REUSEADDR)) { /* pass broadcast- or multicast packets to all multicast pcbs if SOF_REUSEADDR is set on the first match */ struct udp_pcb *mpcb; u8_t p_header_changed = 0; for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { if (mpcb != pcb) { /* compare PCB local addr+port to UDP destination addr+port */ if ((mpcb->local_port == dest) && ((!broadcast && ip_addr_isany(&mpcb->local_ip)) || ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) || #if LWIP_IGMP ip_addr_ismulticast(¤t_iphdr_dest) || #endif /* LWIP_IGMP */ #if IP_SOF_BROADCAST_RECV (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) { #else /* IP_SOF_BROADCAST_RECV */ (broadcast))) { #endif /* IP_SOF_BROADCAST_RECV */ /* pass a copy of the packet to all local matches */ if (mpcb->recv != NULL) { struct pbuf *q; /* for that, move payload to IP header again */ if (p_header_changed == 0) { pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); p_header_changed = 1; } q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); if (q != NULL) { err_t err = pbuf_copy(q, p); if (err == ERR_OK) { /* move payload to UDP data */ pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); } } } } } } if (p_header_changed) { /* and move payload to UDP data again */ pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); } } #endif /* SO_REUSE && SO_REUSE_RXTOALL */ /* callback */ if (pcb->recv != NULL) { /* now the recv function is responsible for freeing p */ pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); } else { /* no recv function registered? then we have to free the pbuf! */ pbuf_free(p); goto end; } } else {
/** * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ void autoip_tmr() { struct netif *netif = netif_list; /* loop through netif's */ while (netif != NULL) { /* only act on AutoIP configured interfaces */ if (netif->autoip != NULL) { if(netif->autoip->lastconflict > 0) { netif->autoip->lastconflict--; } LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", (u16_t)(netif->autoip->state), netif->autoip->ttw)); switch(netif->autoip->state) { case AUTOIP_STATE_PROBING: if(netif->autoip->ttw > 0) { netif->autoip->ttw--; } else { if(netif->autoip->sent_num >= PROBE_NUM) { netif->autoip->state = AUTOIP_STATE_ANNOUNCING; netif->autoip->sent_num = 0; netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); } else { autoip_arp_probe(netif); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); netif->autoip->sent_num++; /* calculate time to wait to next probe */ netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); } } break; case AUTOIP_STATE_ANNOUNCING: if(netif->autoip->ttw > 0) { netif->autoip->ttw--; } else { if(netif->autoip->sent_num == 0) { /* We are here the first time, so we waited ANNOUNCE_WAIT seconds * Now we can bind to an IP address and use it. * * autoip_bind calls netif_set_up. This triggers a gratuitous ARP * which counts as an announcement. */ autoip_bind(netif); } else { autoip_arp_announce(netif); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); } netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; netif->autoip->sent_num++; if(netif->autoip->sent_num >= ANNOUNCE_NUM) { netif->autoip->state = AUTOIP_STATE_BOUND; netif->autoip->sent_num = 0; netif->autoip->ttw = 0; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); } } break; } } /* proceed to next network interface */ netif = netif->next; } }