/** * Return a connection's local or remote address * Called from netconn_getaddr * * @param msg the api_msg_msg pointing to the connection */ void lwip_netconn_do_getaddr(struct api_msg_msg *msg) { if (msg->conn->pcb.ip != NULL) { if (msg->msg.ad.local) { ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), API_EXPR_DEREF(msg->msg.ad.ipaddr), msg->conn->pcb.ip->local_ip); } else { ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), API_EXPR_DEREF(msg->msg.ad.ipaddr), msg->conn->pcb.ip->remote_ip); } msg->err = ERR_OK; switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: if (msg->msg.ad.local) { API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; } else { /* return an error as connecting is only a helper for upper layers */ msg->err = ERR_CONN; } break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: if (msg->msg.ad.local) { API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; } else { if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { msg->err = ERR_CONN; } else { API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; } } break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: if ((msg->msg.ad.local == 0) && ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { /* pcb is not connected and remote name is requested */ msg->err = ERR_CONN; } else { API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); } break; #endif /* LWIP_TCP */ default: LWIP_ASSERT("invalid netconn_type", 0); break; } } else { msg->err = ERR_CONN; } TCPIP_APIMSG_ACK(msg); }
/** * Receive callback function for RAW netconns. * Doesn't 'eat' the packet, only references it and sends it to * conn->recvmbox * * @see raw.h (struct raw_pcb.recv) for parameters and return value */ static u8_t recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr) { struct pbuf *q; struct netbuf *buf; struct netconn *conn; LWIP_UNUSED_ARG(addr); conn = (struct netconn *)arg; if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { #if LWIP_SO_RCVBUF int recv_avail; SYS_ARCH_GET(conn->recv_avail, recv_avail); if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { return 0; } #endif /* LWIP_SO_RCVBUF */ /* copy the whole packet into new pbufs */ q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); if(q != NULL) { if (pbuf_copy(q, p) != ERR_OK) { pbuf_free(q); q = NULL; } } if (q != NULL) { u16_t len; buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); if (buf == NULL) { pbuf_free(q); return 0; } buf->p = q; buf->ptr = q; ipX_addr_copy(PCB_ISIPV6(pcb), buf->addr, *ipX_current_src_addr()); buf->port = pcb->protocol; len = q->tot_len; if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return 0; } else { #if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); #endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } } } return 0; /* do not eat the packet */ }
static void pxdns_query(struct pxdns *pxdns, struct udp_pcb *pcb, struct pbuf *p, ipX_addr_t *addr, u16_t port) { struct request *req; int sent; if (pxdns->nresolvers == 0) { /* nothing we can do */ pbuf_free(p); return; } req = calloc(1, sizeof(struct request) - 1 + p->tot_len); if (req == NULL) { pbuf_free(p); return; } /* copy request data */ req->size = p->tot_len; pbuf_copy_partial(p, req->data, p->tot_len, 0); /* save client identity and client's request id */ req->pcb = pcb; ipX_addr_copy(PCB_ISIPV6(pcb), req->client_addr, *addr); req->client_port = port; memcpy(&req->client_id, req->data, sizeof(req->client_id)); /* slap our request id onto it */ req->id = pxdns->id++; memcpy(req->data, &req->id, sizeof(u16_t)); /* resolver to forward to */ req->generation = pxdns->generation; req->residx = 0; /* prepare for relaying the reply back to guest */ req->msg_reply.type = TCPIP_MSG_CALLBACK_STATIC; req->msg_reply.sem = NULL; req->msg_reply.msg.cb.function = pxdns_pcb_reply; req->msg_reply.msg.cb.ctx = (void *)req; DPRINTF2(("%s: req=%p: client id %d -> id %d\n", __func__, (void *)req, req->client_id, req->id)); pxdns_request_register(pxdns, req); sent = pxdns_forward_outbound(pxdns, req); if (!sent) { sent = pxdns_rexmit(pxdns, req); } if (!sent) { pxdns_request_deregister(pxdns, req); pxdns_request_free(req); } }