示例#1
0
/**
 * Enqueues a new fragment into the fragment queue
 * @param fraghdr points to the new fragments IP hdr
 * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space)
 * @return A pointer to the queue location into which the fragment was enqueued
 */
static struct ip_reassdata*
ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
{
  struct ip_reassdata* ipr;
  /* No matching previous fragment found, allocate a new reassdata struct */
  ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
  if (ipr == NULL) {
#if IP_REASS_FREE_OLDEST
    if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
      ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
    }
    if (ipr == NULL)
#endif /* IP_REASS_FREE_OLDEST */
    {
      IPFRAG_STATS_INC(ip_frag.memerr);
      LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n"));
      return NULL;
    }
  }
  memset(ipr, 0, sizeof(struct ip_reassdata));
  ipr->timer = IP_REASS_MAXAGE;

  sys_lock_acquire( &ip_frag_lock );
  /* enqueue the new structure to the front of the list */
  ipr->next = reassdatagrams;
  reassdatagrams = ipr;
  sys_lock_release( &ip_frag_lock );

  /* copy the ip header for later tests and input */
  /* @todo: no ip options supported? */
  SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN);
  return ipr;
}
/**
 * Attempt to reclaim some memory from queued out-of-sequence TCP segments
 * if we run out of pool pbufs. It's better to give priority to new packets
 * if we're running out.
 *
 * This must be done in the correct thread context therefore this function
 * can only be used with NO_SYS=0 and through tcpip_callback.
 */
static void
pbuf_free_ooseq(void* arg)
{
  struct tcp_pcb* pcb;
  SYS_ARCH_DECL_PROTECT(old_level);
  LWIP_UNUSED_ARG(arg);

  SYS_ARCH_PROTECT(old_level);
  pbuf_free_ooseq_queued = 0;
  SYS_ARCH_UNPROTECT(old_level);

  sys_lock_acquire( &tcp_lock );

  for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
    if (NULL != pcb->ooseq) {
	  sys_lock_release( &tcp_lock );
      /** Free the ooseq pbufs of one PCB only */
      LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
      tcp_segs_free(pcb->ooseq);
      pcb->ooseq = NULL;
      return;
    }
  }
  sys_lock_release( &tcp_lock );
}
示例#3
0
// (exercise 8 code)
void print_to_screen(uint16_t * volatile* cursorpos_ptr, int printch) {
	int k;
	while (1) {
		sys_lock_acquire(&k);
		if (k == 1) break;
		sys_yield();
	}
	*(*cursorpos_ptr)++ = printch;
	k = 0;
	sys_lock_release(&k);
	if (k != 1) sys_exit(1);
}
示例#4
0
struct ip_reassdata* ip_reass_lookup_dg( struct ip_hdr *fraghdr )
{
	struct ip_reassdata *ipr;

	sys_lock_acquire( &ip_frag_lock );
	for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) {
		if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
			break;
		}
	}
	sys_lock_release( &ip_frag_lock );

	return ipr;
}
示例#5
0
/**
 * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs.
 * @param ipr points to the queue entry to dequeue
 */
static void
ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
{
  sys_lock_acquire( &ip_frag_lock );
  /* dequeue the reass struct  */
  if (reassdatagrams == ipr) {
    /* it was the first in the list */
    reassdatagrams = ipr->next;
  } else {
    /* it wasn't the first, so it must have a valid 'prev' */
    LWIP_ASSERT("sanity check linked list", prev != NULL);
    prev->next = ipr->next;
  }
  sys_lock_release( &ip_frag_lock );

  /* now we can free the ip_reass struct */
  memp_free(MEMP_REASSDATA, ipr);
}
struct udp_pcb* udp_lookup_pcb( ip_addr_t *src_ip, ip_addr_t *dst_ip, u16_t src_port, u16_t dst_port )
{
	struct udp_pcb *pcb = NULL;
	struct udp_pcb *uncon_pcb =NULL;
	u8_t local_match;
	u8_t broadcast;

	sys_lock_acquire( &udp_lock );

    /* 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;
 
      /* compare PCB local addr+port to UDP destination addr+port */
      if ((pcb->local_port == dst_port) && (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&(pcb->local_ip), dst_ip)))
	  {
		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_port) &&
          (ip_addr_isany(&pcb->remote_ip) ||
           ip_addr_cmp(&(pcb->remote_ip), src_ip))) 
	  {
        break;
      }
    }
    /* no fully matching pcb found? then look for an unconnected pcb */
    if (pcb == NULL) {
      pcb = uncon_pcb;
    }

	sys_lock_release( &udp_lock );
	return pcb;
}
示例#7
0
void trap_kernel_handler(struct user_context *user_ctx)
{
	_debug("...... in %s, code = %p\n",
			__func__, user_ctx->code & ~YALNIX_PREFIX);

	switch (user_ctx->code) {
	case YALNIX_FORK:
		SET_RET(user_ctx, sys_fork(user_ctx));
		break;
	case YALNIX_EXEC:
		sys_exec((char *)user_ctx->regs[0], (char **)user_ctx->regs[1],
				user_ctx);
		break;
	case YALNIX_EXIT:
		sys_exit(user_ctx->regs[0], user_ctx);
		break;
	case YALNIX_WAIT:
		if (!FROM_USER_SPACE(user_ctx->regs[0])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_wait((int *)user_ctx->regs[0], user_ctx));
		break;
	case YALNIX_GETPID:
		SET_RET(user_ctx, sys_getpid());
		break;
	case YALNIX_BRK:
		SET_RET(user_ctx, sys_brk(user_ctx->regs[0]));
		break;
	case YALNIX_DELAY:
		SET_RET(user_ctx, sys_delay(user_ctx->regs[0], user_ctx));
		break;
	case YALNIX_TTY_READ:
		if (!FROM_USER_SPACE(user_ctx->regs[1])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_tty_read(user_ctx->regs[0],
				(char *)user_ctx->regs[1],
				user_ctx->regs[2],
				user_ctx));
		break;
	case YALNIX_TTY_WRITE:
		if (!FROM_USER_SPACE(user_ctx->regs[1])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_tty_write(user_ctx->regs[0],
				(char *)user_ctx->regs[1],
				user_ctx->regs[2],
				user_ctx));
		break;
	case YALNIX_PIPE_INIT:
		if (!FROM_USER_SPACE(user_ctx->regs[0])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_pipe_init((unsigned int *)
					user_ctx->regs[0]));
		break;
	case YALNIX_PIPE_READ:
		if (!FROM_USER_SPACE(user_ctx->regs[1])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_pipe_read(user_ctx->regs[0],
					(char *)user_ctx->regs[1],
					user_ctx->regs[2],
					user_ctx));
		break;
	case YALNIX_PIPE_WRITE:
		if (!FROM_USER_SPACE(user_ctx->regs[1])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_pipe_write(user_ctx->regs[0],
					(char *)user_ctx->regs[1],
					user_ctx->regs[2],
					user_ctx));
		break;
	case YALNIX_LOCK_INIT:
		if (!FROM_USER_SPACE(user_ctx->regs[0])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_lock_init((unsigned int *)
					user_ctx->regs[0]));
		break;
	case YALNIX_LOCK_ACQUIRE:
		SET_RET(user_ctx, sys_lock_acquire(user_ctx->regs[0],
						user_ctx));
		break;
	case YALNIX_LOCK_RELEASE:
		SET_RET(user_ctx, sys_lock_release(user_ctx->regs[0]));
		break;
	case YALNIX_CVAR_INIT:
		if (!FROM_USER_SPACE(user_ctx->regs[0])) {
			_error("Bad man! Please pass user space pointer!\n");
			sys_exit(ERROR, user_ctx);
		}
		SET_RET(user_ctx, sys_cvar_init((unsigned int *)
					user_ctx->regs[0]));
		break;
	case YALNIX_CVAR_WAIT:
		SET_RET(user_ctx, sys_cvar_wait(user_ctx->regs[0],
					user_ctx->regs[1],
					user_ctx));
		break;
	case YALNIX_CVAR_SIGNAL:
		SET_RET(user_ctx, sys_cvar_signal(user_ctx->regs[0]));
		break;
	case YALNIX_CVAR_BROADCAST:
		SET_RET(user_ctx, sys_cvar_broadcast(user_ctx->regs[0]));
		break;
	case YALNIX_RECLAIM:
		SET_RET(user_ctx, sys_reclaim(user_ctx->regs[0]));
		break;
	case YALNIX_CUSTOM_0:
		SET_RET(user_ctx, sys_fork_share(user_ctx));
		break;
	}

	return;
}
/**
 * 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(&current_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), &current_iphdr_src))) {
          pcb = inp->dhcp->pcb;
        }
      }
    }
  } else
#endif /* LWIP_DHCP */
  {
    prev = NULL;
    local_match = 0;
    uncon_pcb = NULL;

	sys_lock_acquire( &udp_lock );

    /* 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) &&
          ((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
           ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest) ||
#if LWIP_IGMP
           ip_addr_ismulticast(&current_iphdr_dest) ||
#endif /* LWIP_IGMP */
#if IP_SOF_BROADCAST_RECV
           (broadcast && (pcb->so_options & SOF_BROADCAST)))) {
#else  /* IP_SOF_BROADCAST_RECV */
           (broadcast))) {
#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), &current_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;
    }
	sys_lock_release( &udp_lock );
  }

  /* Check checksum if this is a match or if it was directed at us. */
  if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &current_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, &current_iphdr_src, &current_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(&current_iphdr_dest)) &&
          ((pcb->so_options & SOF_REUSEADDR) != 0)) {
        /* 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), &current_iphdr_dest) ||
#if LWIP_IGMP
                 ip_addr_ismulticast(&current_iphdr_dest) ||
#endif /* LWIP_IGMP */
#if IP_SOF_BROADCAST_RECV
                 (broadcast && (mpcb->so_options & 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 {
/**
 * 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 ((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"));

	sys_lock_acquire( &tcp_lock );
    pcb = tcp_active_pcbs;
	tcp_active_pcbs = NULL;
	sys_lock_release( &tcp_lock );

    while (pcb != NULL) {
      /* PCB bound to current local interface address? */
      if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
#if LWIP_AUTOIP
        /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
        && !ip_addr_islinklocal(&(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 %p\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(&(lpcb->local_ip)))) &&
          (ip_addr_cmp(&(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(&(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[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)));
}