static vsf_err_t vsfip_telnetd_session_rx_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsfip_telnetd_session_t *session = (struct vsfip_telnetd_session_t *)pt->user_data; uint32_t len; vsf_err_t err; vsfsm_pt_begin(pt); session->caller_rxpt.sm = pt->sm; while (!session->disconnect) { session->caller_rxpt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_recv(&session->caller_rxpt, evt, session->so, &session->so->remote_sockaddr, &session->inbuf); if (err > 0) return err; else if (err < 0) { session->disconnect = true; // fake on_in event, just to wakeup tx_thread to exit vsfip_telnetd_session_stream_on_in(session); break; } while (session->inbuf->app.size > 0) { len = stream_write(session->stream_rx, &session->inbuf->app); if (!len && vsfsm_sem_pend(&session->stream_rx_sem, pt->sm)) { vsfsm_pt_wfe(pt, VSFIP_TELNETD_EVT_STREAM_OUT); continue; } session->inbuf->app.buffer += len; session->inbuf->app.size -= len; } vsfip_buffer_release(session->inbuf); } vsfsm_pt_end(pt); return VSFERR_NONE; }
void vsfip_eth_input(struct vsfip_buffer_t *buf) { struct vsfip_ethhead_t *head = (struct vsfip_ethhead_t *)buf->buf.buffer; buf->buf.buffer += sizeof(struct vsfip_ethhead_t); buf->buf.size -= sizeof(struct vsfip_ethhead_t); switch (BE_TO_SYS_U16(head->type)) { case VSFIP_ETH_TYPE_IP: vsfip_netif_ip4_input(buf); break; case VSFIP_ETH_TYPE_IP6: vsfip_netif_ip6_input(buf); break; case VSFIP_ETH_TYPE_ARP: vsfip_netif_arp_input(buf); break; default: case VSFIP_ETH_TYPE_RARP: // not supported vsfip_buffer_release(buf); } }
static void vsfip_dhcpd_input(void *param, struct vsfip_buffer_t *buf) { struct vsfip_dhcpd_t *dhcpd = (struct vsfip_dhcpd_t *)param; struct vsfip_netif_t *netif = dhcpd->netif; struct vsfip_dhcphead_t *head; struct vsfip_ipmac_assoc *assoc; uint8_t optlen, op; uint8_t *optptr; if (netif != buf->netif) { goto exit; } head = (struct vsfip_dhcphead_t *)buf->app.buffer; if ((head->op != DHCP_TOSERVER) || (head->magic != SYS_TO_BE_U32(DHCP_MAGIC)) || (head->htype != VSFIP_ETH_HWTYPE) || (head->hlen != 6)) { goto exit; } optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_MSGTYPE, &optptr); if (optlen != DHCPOPT_MSGTYPE_LEN) { goto exit; } switch (optptr[0]) { case DHCPOP_DISCOVER: assoc = vsfip_dhcpd_get_assoc(netif, head->chaddr); if (NULL == assoc) { goto exit; } op = DHCPOP_OFFER; common_reply: head->op = DHCP_TOCLIENT; head->secs = 0; head->flags = 0; head->yiaddr = assoc->ip.addr.s_addr; head->siaddr = netif->ipaddr.addr.s_addr; buf->app.size = sizeof(*head); dhcpd->optlen = 0; vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_MSGTYPE, DHCPOPT_MSGTYPE_LEN, &op); vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_SERVERID, netif->ipaddr.size, netif->ipaddr.addr.s_addr_buf); { uint32_t lease_time = SYS_TO_BE_U32(0x80000000); vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_LEASE_TIME, netif->ipaddr.size, (uint8_t *)&lease_time); } vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_SUBNETMASK, netif->netmask.size, netif->netmask.addr.s_addr_buf); vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_ROUTER, netif->ipaddr.size, netif->ipaddr.addr.s_addr_buf); vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_DNSSERVER, netif->ipaddr.size, netif->ipaddr.addr.s_addr_buf); #ifdef VSFIP_CFG_HOSTNAME vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_HOSTNAME, strlen(VSFIP_CFG_HOSTNAME), (uint8_t *)VSFIP_CFG_HOSTNAME); #endif #ifdef VSFIP_CFG_DOMAIN vsfip_dhcp_append_opt(buf, &dhcpd->optlen, DHCPOPT_DOMAIN, strlen(VSFIP_CFG_DOMAIN), (uint8_t *)VSFIP_CFG_DOMAIN); #endif vsfip_dhcp_end_opt(buf, &dhcpd->optlen); dhcpd->sockaddr.sin_addr.addr.s_addr = assoc->ip.addr.s_addr; vsfip_netif_arp_add_assoc(dhcpd->netif, assoc->mac.size, assoc->mac.addr.s_addr_buf, assoc->ip.size, assoc->ip.addr.s_addr_buf); vsfip_udp_async_send(dhcpd->so, &dhcpd->sockaddr, buf); dhcpd->so->remote_sockaddr.sin_addr.addr.s_addr = VSFIP_IPADDR_ANY; return; case DHCPOP_REQUEST: assoc = vsfip_dhcpd_get_assoc(netif, head->chaddr); if (NULL == assoc) { goto exit; } optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_REQIP, &optptr); if ((4 == optlen) && (*(uint32_t *)optptr != assoc->ip.addr.s_addr)) { op = DHCPOP_NAK; } else { op = DHCPOP_ACK; } goto common_reply; } exit: vsfip_buffer_release(buf); }
static vsf_err_t vsfip_telnetd_session_tx_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsfip_telnetd_session_t *session = (struct vsfip_telnetd_session_t *)pt->user_data; uint32_t len; vsf_err_t err; vsfsm_pt_begin(pt); session->caller_txpt.sm = pt->sm; while (!session->disconnect) { len = stream_get_data_size(session->stream_tx); if (!len && vsfsm_sem_pend(&session->stream_tx_sem, pt->sm)) { vsfsm_pt_wfe(pt, VSFIP_TELNETD_EVT_STREAM_IN); if (session->disconnect) break; continue; } retry_alloc_buf: session->outbuf = VSFIP_TCPBUF_GET(len); if (NULL == session->outbuf) { vsfsm_pt_delay(pt, 5); if (session->disconnect) break; goto retry_alloc_buf; } session->outbuf->app.size = stream_read(session->stream_tx, &session->outbuf->app); if (!session->outbuf->app.size) { vsfip_buffer_release(session->outbuf); continue; } session->caller_txpt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_send(&session->caller_txpt, evt, session->so, &session->so->remote_sockaddr, session->outbuf, false); if (err > 0) return err; else if (err < 0) { session->disconnect = true; } } // close tcp socket session->caller_txpt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_close(&session->caller_txpt, evt, session->so); if (err > 0) return err; // close socket no matter if tcp closed OK or not vsfip_close(session->so); session->connected = false; vsfsm_pt_end(pt); return VSFERR_NONE; }
static void vsfip_dhcpc_input(void *param, struct vsfip_buffer_t *buf) { struct vsfip_dhcpc_t *dhcpc = (struct vsfip_dhcpc_t *)param; struct vsfip_netif_t *netif = dhcpc->netif; struct vsfip_dhcphead_t *head; uint8_t optlen; uint8_t *optptr; head = (struct vsfip_dhcphead_t *)buf->app.buffer; if ((head->op != DHCP_TOCLIENT) || (head->magic != SYS_TO_BE_U32(DHCP_MAGIC)) || memcmp(head->chaddr, netif->macaddr.addr.s_addr_buf, netif->macaddr.size) || (head->xid != dhcpc->xid)) { goto exit; } optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_MSGTYPE, &optptr); if (optlen != DHCPOPT_MSGTYPE_LEN) { goto exit; } switch (optptr[0]) { case DHCPOP_OFFER: dhcpc->ipaddr.size = 4; dhcpc->ipaddr.addr.s_addr = head->yiaddr; vsfsm_post_evt(&dhcpc->sm, VSFIP_DHCP_EVT_SEND_REQUEST); break; case DHCPOP_ACK: optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_LEASE_TIME, &optptr); dhcpc->leasetime = (4 == optlen) ? GET_BE_U32(optptr) : 0; optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_RENEW_TIME, &optptr); dhcpc->renew_time = (4 == optlen) ? GET_BE_U32(optptr) : 0; optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_REBINDING_TIME, &optptr); dhcpc->rebinding_time = (4 == optlen) ? GET_BE_U32(optptr) : 0; optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_SUBNETMASK, &optptr); dhcpc->netmask.size = optlen; dhcpc->netmask.addr.s_addr = (4 == optlen) ? *(uint32_t *)optptr : 0; optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_ROUTER, &optptr); dhcpc->gw.size = optlen; dhcpc->gw.addr.s_addr = (4 == optlen) ? *(uint32_t *)optptr : 0; optlen = vsfip_dhcp_get_opt(buf, DHCPOPT_DNSSERVER, &optptr); dhcpc->dns[0].size = dhcpc->dns[1].size = 0; if (optlen >= 4) { dhcpc->dns[0].size = 4; dhcpc->dns[0].addr.s_addr = *(uint32_t *)optptr; if (optlen >= 8) { dhcpc->dns[1].size = 4; dhcpc->dns[1].addr.s_addr = *(uint32_t *)(optptr + 4); } } vsfsm_post_evt(&dhcpc->sm, VSFIP_DHCP_EVT_READY); break; } exit: vsfip_buffer_release(buf); }