예제 #1
0
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;
}
예제 #2
0
파일: vsfip_eth.c 프로젝트: a20084666/vsf
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);
	}
}
예제 #3
0
파일: vsfip_dhcpd.c 프로젝트: ymwcoding/vsf
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);
}
예제 #4
0
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;
}
예제 #5
0
파일: vsfip_dhcpc.c 프로젝트: LewosPeng/vsf
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);
}