예제 #1
0
파일: vsfip_dhcpd.c 프로젝트: ymwcoding/vsf
vsf_err_t vsfip_dhcpd_start(struct vsfip_netif_t *netif,
                            struct vsfip_dhcpd_t *dhcpd)
{
    if ((NULL == netif) || (NULL == dhcpd))
    {
        return VSFERR_FAIL;
    }

    dhcpd->alloc_idx = 1;
    netif->dhcp.dhcpd = dhcpd;
    dhcpd->netif = netif;
    memset(&dhcpd->assoc, 0, sizeof(dhcpd->assoc));

    dhcpd->sockaddr.sin_port = DHCP_CLIENT_PORT;
    dhcpd->sockaddr.sin_addr.size = 4;

    dhcpd->so = vsfip_socket(AF_INET, IPPROTO_UDP);
    if (NULL == dhcpd->so)
    {
        goto cleanup;
    }
    vsfip_socket_cb(dhcpd->so, dhcpd, vsfip_dhcpd_input, NULL);
    if (vsfip_bind(dhcpd->so, DHCP_SERVER_PORT))
    {
        goto cleanup;
    }
    return vsfip_listen(dhcpd->so, 0);
cleanup:
    if (dhcpd->so != NULL)
    {
        vsfip_close(dhcpd->so);
        dhcpd->so = NULL;
    }
    return VSFERR_FAIL;
}
예제 #2
0
파일: vsfip_dhcpc.c 프로젝트: LewosPeng/vsf
static struct vsfsm_state_t *
vsfip_dhcpc_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
	struct vsfip_dhcpc_t *dhcpc = (struct vsfip_dhcpc_t *)sm->user_data;
	struct vsfip_netif_t *netif = dhcpc->netif;

	switch (evt)
	{
	case VSFSM_EVT_INIT:
		dhcpc->ready = true;
		dhcpc->retry = 0;

	retry:
		dhcpc->xid = vsfip_dhcpc.xid++;
		dhcpc->so = vsfip_socket(AF_INET, IPPROTO_UDP);
		if (NULL == dhcpc->so)
		{
			goto cleanup;
		}
		vsfip_socket_cb(dhcpc->so, dhcpc, vsfip_dhcpc_input, NULL);
		if (vsfip_bind(dhcpc->so, DHCP_CLIENT_PORT))
		{
			goto cleanup;
		}
		vsfip_listen(dhcpc->so, 0);

		// if address already allocated, do resume, send request again
		if (dhcpc->ipaddr.size != 0)
		{
			goto dhcp_request;
		}

		// discover
		memset(&netif->ipaddr, 0, sizeof(netif->ipaddr));
		dhcpc->ipaddr.size = 0;
		if (vsfip_dhcpc_init_msg(dhcpc, (uint8_t)DHCPOP_DISCOVER) < 0)
		{
			goto cleanup;
		}
		vsfip_dhcp_end_opt(dhcpc->outbuffer, &dhcpc->optlen);
		dhcpc->sockaddr.sin_addr.addr.s_addr = 0xFFFFFFFF;
		vsfip_udp_async_send(dhcpc->so, &dhcpc->sockaddr, dhcpc->outbuffer);
		dhcpc->so->remote_sockaddr.sin_addr.addr.s_addr = VSFIP_IPADDR_ANY;

		dhcpc->to = vsftimer_create(sm, 5000, 1, VSFIP_DHCP_EVT_TIMEROUT);
		break;
	case VSFIP_DHCP_EVT_SEND_REQUEST:
	dhcp_request:
		vsftimer_free(dhcpc->to);
		if (vsfip_dhcpc_init_msg(dhcpc, (uint8_t)DHCPOP_REQUEST) < 0)
		{
			goto cleanup;
		}
		vsfip_dhcp_append_opt(dhcpc->outbuffer, &dhcpc->optlen,
								DHCPOPT_REQIP, dhcpc->ipaddr.size,
								dhcpc->ipaddr.addr.s_addr_buf);
		vsfip_dhcp_end_opt(dhcpc->outbuffer, &dhcpc->optlen);
		dhcpc->sockaddr.sin_addr.addr.s_addr = 0xFFFFFFFF;
		vsfip_udp_async_send(dhcpc->so, &dhcpc->sockaddr, dhcpc->outbuffer);
		dhcpc->so->remote_sockaddr.sin_addr.addr.s_addr = VSFIP_IPADDR_ANY;

		dhcpc->to = vsftimer_create(sm, 2000, 1, VSFIP_DHCP_EVT_TIMEROUT);
		break;
	case VSFIP_DHCP_EVT_READY:
		vsftimer_free(dhcpc->to);
		// update netif->ipaddr
		dhcpc->ready = 1;
		netif->ipaddr = dhcpc->ipaddr;
		netif->gateway = dhcpc->gw;
		netif->netmask = dhcpc->netmask;
		netif->dns[0] = dhcpc->dns[0];
		netif->dns[1] = dhcpc->dns[1];

		// timer out for resume
//		vsftimer_create(sm, 2000, 1, VSFIP_DHCP_EVT_TIMEROUT);
		goto cleanup;
		break;
	case VSFIP_DHCP_EVT_TIMEROUT:
		// maybe need to resume, set the ready to false
		dhcpc->ready = false;
	cleanup:
		if (dhcpc->so != NULL)
		{
			vsfip_close(dhcpc->so);
			dhcpc->so = NULL;
		}
		if (!dhcpc->ready && (++dhcpc->retry < VSFIP_DHCPC_RETRY_CNT))
		{
			goto retry;
		}

		// notify callder
		if (dhcpc->update_sem.evt != VSFSM_EVT_NONE)
		{
			vsfsm_sem_post(&dhcpc->update_sem);
		}
		break;
	}

	return NULL;
}