/** * New proxied UDP conversation created. * Global callback for udp_proxy_accept(). */ static void pxudp_pcb_accept(void *arg, struct udp_pcb *newpcb, struct pbuf *p, ip_addr_t *addr, u16_t port) { struct pxudp *pxudp; ipX_addr_t dst_addr; int mapping; int sdom; SOCKET sock; LWIP_ASSERT1(newpcb != NULL); LWIP_ASSERT1(p != NULL); LWIP_UNUSED_ARG(arg); pxudp = pxudp_allocate(); if (pxudp == NULL) { DPRINTF(("pxudp_allocate: failed\n")); udp_remove(newpcb); pbuf_free(p); return; } sdom = PCB_ISIPV6(newpcb) ? PF_INET6 : PF_INET; mapping = pxremap_outbound_ipX(PCB_ISIPV6(newpcb), &dst_addr, &newpcb->local_ip); #if 0 /* XXX: DNS IPv6->IPv4 remapping hack */ if (mapping == PXREMAP_MAPPED && newpcb->local_port == 53 && PCB_ISIPV6(newpcb)) { /* * "Remap" DNS over IPv6 to IPv4 since Ubuntu dnsmasq does not * listen on IPv6. */ sdom = PF_INET; ipX_addr_set_loopback(0, &dst_addr); } #endif /* DNS IPv6->IPv4 remapping hack */ sock = proxy_connected_socket(sdom, SOCK_DGRAM, &dst_addr, newpcb->local_port); if (sock == INVALID_SOCKET) { udp_remove(newpcb); pbuf_free(p); return; } pxudp->sock = sock; pxudp->pcb = newpcb; udp_recv(newpcb, pxudp_pcb_recv, pxudp); pxudp->pmhdl.callback = pxudp_pmgr_pump; pxudp_chan_send(POLLMGR_CHAN_PXUDP_ADD, pxudp); /* dispatch directly instead of calling pxudp_pcb_recv() */ pxudp_pcb_forward_outbound(pxudp, p, addr, port); }
/** * udp_recv() callback. */ static void pxudp_pcb_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) { struct pxudp *pxudp = (struct pxudp *)arg; LWIP_ASSERT1(pxudp != NULL); LWIP_ASSERT1(pcb == pxudp->pcb); LWIP_UNUSED_ARG(pcb); if (p != NULL) { pxudp_pcb_forward_outbound(pxudp, p, addr, port); } else { pxudp_pcb_expired(pxudp); } }