Пример #1
0
static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
							gpointer user_data)
{
	GDHCPServer *dhcp_server = user_data;
	struct dhcp_packet packet;
	struct dhcp_lease *lease;
	uint32_t requested_nip = 0;
	uint8_t type, *server_id_option, *request_ip_option, *host_name;
	int re;

	GDHCPOptionType option_type;
	char *option_value;

	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
		dhcp_server->listener_watch = 0;
		return FALSE;
	}

	re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd);
	if (re < 0)
		return TRUE;

	type = check_packet_type(&packet);
	if (type == 0)
		return TRUE;

	server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID);
	if (server_id_option) {
		uint32_t server_nid = get_be32(server_id_option);

		if (server_nid != dhcp_server->server_nip)
			return TRUE;
	}

	request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP);
	if (request_ip_option)
		requested_nip = get_be32(request_ip_option);

	lease = find_lease_by_mac(dhcp_server, packet.chaddr);

	switch (type) {
	case DHCPDISCOVER:
		debug(dhcp_server, "Received DISCOVER");

		send_offer(dhcp_server, &packet, lease, requested_nip);
		break;
	case DHCPREQUEST:
		debug(dhcp_server, "Received REQUEST NIP %d",
							requested_nip);
		if (requested_nip == 0) {
			requested_nip = packet.ciaddr;
			if (requested_nip == 0)
				break;
		}

		if (lease && requested_nip == lease->lease_nip) {
			debug(dhcp_server, "Sending ACK");
			host_name =
				dhcp_get_option(&packet,
					 DHCP_HOST_NAME);
			option_type =
				dhcp_get_code_type(DHCP_HOST_NAME);
			option_value =
				malloc_option_value_string(host_name,
					 option_type);

			send_ACK(dhcp_server, &packet,
				lease->lease_nip);

			if (dhcp_server->save_ack_lease_func)
				dhcp_server->save_ack_lease_func(
					option_value,
					lease->lease_mac,
					lease->lease_nip);

			g_free(option_value);

			break;
		}

		if (server_id_option || !lease) {
			debug(dhcp_server, "Sending NAK");
			send_NAK(dhcp_server, &packet);
		}

		break;
	case DHCPDECLINE:
		debug(dhcp_server, "Received DECLINE");

		if (!server_id_option)
			break;

		if (!request_ip_option)
			break;

		if (!lease)
			break;

		if (requested_nip == lease->lease_nip)
			remove_lease(dhcp_server, lease);

		break;
	case DHCPRELEASE:
		debug(dhcp_server, "Received RELEASE");

		if (!server_id_option)
			break;

		if (!lease)
			break;

		if (packet.ciaddr == lease->lease_nip)
			lease_set_expire(dhcp_server, lease,
					time(NULL));
		break;
	case DHCPINFORM:
		debug(dhcp_server, "Received INFORM");
		send_inform(dhcp_server, &packet);
		break;
	}

	return TRUE;
}
Пример #2
0
void handle_dhcp(struct server_conf *conf, pcap_t *p, struct pktbuf *inpkt) {
    unsigned char tag, len;
    int i, j;
    int msgtype;
    union ip_address ip;
    unsigned char buffer[512];
    guint32 lease;
    unsigned char *options = inpkt->dhcp_packet->options;
    unsigned char *srcmac = inpkt->eth_header->h_source;
    struct client_conf *client;

#if DEBUG
    fprintf(stderr, "Optionslen: %d\n", inpkt->optlen);
#endif
    if (inpkt->optlen < 6) return;
#if DEBUG
    fprintf(stderr, "%d.%d.%d.%d\n", options[0], options[1], options[2], options[3]);
#endif

    // check the magic cookie
    if (!(options[0] == 99 && options[1] == 130
                && options[2]== 83 && options[3] == 99)) {
        return;
    }

    i = 4;

    while (1) {
        CHKOPTLEN(2);
        tag = options[i++];
        if (tag == 0) continue;
        if (tag == 255) goto END;

        len = options[i++];

        CHKOPTLEN(len);

        switch (tag) {
            case 1:
                // Subnet Mask
                if (len != 4) {
                    fprintf(stderr, "Malformed len in subnet mask tag: Should be 4 but is %d\n", len);
                    return;
                }

                ip.a[0] = options[i++]; ip.a[1] = options[i++]; ip.a[2] = options[i++]; ip.a[3] = options[i++];

                printf("Subnet Mask: %d.%d.%d.%d\n", ip.a[0], ip.a[1], ip.a[2], ip.a[3]);
                break;
            case 3:
                // Default Gateway
                if (len < 4) {
                    fprintf(stderr, "Malformed len in router tag: Should 4 or greater but is %d\n", len);
                    return;
                }

                if (len % 4 != 0) {
                    fprintf(stderr, "Malformed len in router tag: Should be a multiple of 4 but is %d\n", len);
                    return;
                }

                len /= 4;
                for (j = 0; j < len; j++) {
                    ip.a[0] = options[i++];
                    ip.a[1] = options[i++];
                    ip.a[2] = options[i++];
                    ip.a[3] = options[i++];

#if DEBUG
                    printf("Router %d: %d.%d.%d.%d\n", j + 1, ip.a[0], ip.a[1], ip.a[2], ip.a[3]);
#endif
                }
                break;
            case 6:
                // DNS Servers
                if (len < 4) {
                    fprintf(stderr, "Malformed len in DNS tag: Should 4 or greater but is %d\n", len);
                    return;
                }

                if (len % 4 != 0) {
                    fprintf(stderr, "Malformed len in DNS tag: Should be a multiple of 4 but is %d\n", len);
                    return;
                }

                len /= 4;
                for (j = 0; j < len; j++) {
                    ip.a[0] = options[i++];
                    ip.a[1] = options[i++];
                    ip.a[2] = options[i++];
                    ip.a[3] = options[i++];

#if DEBUG
                    printf("DNS Server %d: %d.%d.%d.%d\n", j + 1, ip.a[0], ip.a[1], ip.a[2], ip.a[3]);
#endif
                }
                break;
                break;
            case 12:
                // Host Name Option
                memcpy(buffer, &options[i], len);
                buffer[len] = '\0';
#if DEBUG
                printf("Hostname: %s\n", buffer);
#endif
                i += len;
                break;
            case 50:
                // Requested IP
                if (len != 4) {
                    fprintf(stderr, "Malformed len in requested IP tag: Should be 4 but is %d\n", len);
                    return;
                }

                ip.a[0] = options[i++];
                ip.a[1] = options[i++];
                ip.a[2] = options[i++];
                ip.a[3] = options[i++];

                printf("Requested IP: %d.%d.%d.%d\n", ip.a[0], ip.a[1], ip.a[2], ip.a[3]);
                break;
                break;
            case 51:
                // Lease Time in Seconds
                lease = *((guint32*) &options[i]);
                lease = ntohl(lease);

                printf("Lease: %ld\n", (long) lease);
                i += len;
                break;
            case 53:
                // DHCP Message Type
                msgtype = options[i++];
                printf("MSG TYPE: %d\n", msgtype);
                printf("MSG TYPE: %s\n", msgtypes[msgtype]);
                break;
            case 54:
                // Server Identifier
                if (len != 4) {
                    fprintf(stderr, "Malformed len in server identifier tag: Should be 4 but is %d\n", len);
                    return;
                }

                ip.a[0] = options[i++];
                ip.a[1] = options[i++];
                ip.a[2] = options[i++];
                ip.a[3] = options[i++];

                printf("Server Identifier: %d.%d.%d.%d\n", ip.a[0], ip.a[1], ip.a[2], ip.a[3]);
                break;
            case 55:
                printf("DHCP options: ");
                for (j = 0; j < len; j++) {
                    if (j != 0) printf(", ");
                    printf("%d", options[i++]);
                }
                printf("\n");
                break;
            default:
                fprintf(stderr, "ERROR: Unknown DHCP Option Tag: %d\n", tag);
                // skip over this tag
                i += len;
        }
    }

END:

    // we serve only MACs we know
    fprintf(stderr, "Lookup of MAC %x:%x:%x:%x:%x:%x in VLAN %d\n",
            srcmac[0], srcmac[1], srcmac[2], srcmac[3], srcmac[4], srcmac[5], inpkt->vlan);
    client = lookup_client(conf, inpkt->vlan, srcmac);
    if (client == NULL) return;
    fprintf(stderr, "Lookup successful\n");

    if (msgtype == DHCPDISCOVER) {
        send_offer(p, inpkt, client);
    } else if (msgtype == DHCPREQUEST) {
        send_ack(p, inpkt, client);
    }
}
Пример #3
0
static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
							gpointer user_data)
{
	GDHCPServer *dhcp_server = user_data;
	struct dhcp_packet packet;
	struct dhcp_lease *lease;
	uint32_t requested_nip = 0;
	uint8_t type, *server_id_option, *request_ip_option;
	int re;

	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
		dhcp_server->listener_watch = 0;
		return FALSE;
	}

	re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd);
	if (re < 0)
		return TRUE;

	type = check_packet_type(&packet);
	if (type == 0)
		return TRUE;

	server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID);
	if (server_id_option) {
		uint32_t server_nid = dhcp_get_unaligned(
					(uint32_t *) server_id_option);

		if (server_nid != dhcp_server->server_nip)
			return TRUE;
	}

	request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP);
	if (request_ip_option)
		requested_nip = dhcp_get_unaligned(
					(uint32_t *) request_ip_option);

	lease = find_lease_by_mac(dhcp_server, packet.chaddr);

	switch (type) {
		case DHCPDISCOVER:
			debug(dhcp_server, "Received DISCOVER");

			send_offer(dhcp_server, &packet, lease, requested_nip);
		break;
		case DHCPREQUEST:
			debug(dhcp_server, "Received REQUEST NIP %d",
							requested_nip);
			if (requested_nip == 0) {
				requested_nip = packet.ciaddr;
				if (requested_nip == 0)
					break;
			}

			if (lease && requested_nip == lease->lease_nip) {
				debug(dhcp_server, "Sending ACK");
				send_ACK(dhcp_server, &packet,
						lease->lease_nip);
				break;
			}

			if (server_id_option || lease == NULL) {
				debug(dhcp_server, "Sending NAK");
				send_NAK(dhcp_server, &packet);
			}

		break;
		case DHCPDECLINE:
			debug(dhcp_server, "Received DECLINE");

			if (server_id_option == NULL)
				break;

			if (request_ip_option == NULL)
				break;

			if (lease == NULL)
				break;

			if (requested_nip == lease->lease_nip)
				remove_lease(dhcp_server, lease);

		break;
		case DHCPRELEASE:
			debug(dhcp_server, "Received RELEASE");

			if (server_id_option == NULL)
				break;

			if (lease == NULL)
				break;

			if (packet.ciaddr == lease->lease_nip)
				lease_set_expire(dhcp_server, lease,
								time(NULL));
		break;
		case DHCPINFORM:
			debug(dhcp_server, "Received INFORM");
			send_inform(dhcp_server, &packet);
		break;
	}

	return TRUE;
}
Пример #4
0
static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
									struct udp_pcb *pcb,
									struct pbuf *p,
									struct ip_addr *addr,
									uint16_t port)
{
		struct dhcps_msg *pmsg_dhcps = NULL;
		sint16_t tlen = 0;
        u16_t i = 0;
	    u16_t dhcps_msg_cnt = 0;
	    u8_t *p_dhcps_msg = NULL;
	    u8_t *data = NULL;

#if DHCPS_DEBUG
    	os_printf("dhcps: handle_dhcp-> receive a packet\n");
#endif
	    if (p==NULL) return;

	    pmsg_dhcps = (struct dhcps_msg *)os_zalloc(sizeof(struct dhcps_msg));
	    if (NULL == pmsg_dhcps){
	    	pbuf_free(p);
	    	return;
	    }
	    p_dhcps_msg = (u8_t *)pmsg_dhcps;
		tlen = p->tot_len;
	    data = p->payload;

#if DHCPS_DEBUG
	    os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
	    os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
#endif		

	    for(i=0; i<p->len; i++){
	        p_dhcps_msg[dhcps_msg_cnt++] = data[i];
#if DHCPS_DEBUG					
			os_printf("%02x ",data[i]);
			if((i+1)%16 == 0){
				os_printf("\n");
			}
#endif
	    }
		
		if(p->next != NULL) {
#if DHCPS_DEBUG
	        os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
	        os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
	        os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
#endif
			
	        data = p->next->payload;
	        for(i=0; i<p->next->len; i++){
	            p_dhcps_msg[dhcps_msg_cnt++] = data[i];
#if DHCPS_DEBUG					
				os_printf("%02x ",data[i]);
				if((i+1)%16 == 0){
					os_printf("\n");
				}
#endif
			}
		}

		/*
	     * DHCP �ͻ���������Ϣ����
	    */
#if DHCPS_DEBUG
    	os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
#endif
		
        switch(parse_msg(pmsg_dhcps, tlen - 240)) {

	        case DHCPS_STATE_OFFER://1
#if DHCPS_DEBUG            
            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
#endif			
	             send_offer(pmsg_dhcps);
	             break;
	        case DHCPS_STATE_ACK://3
#if DHCPS_DEBUG
            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
#endif			
	             send_ack(pmsg_dhcps);
	             break;
	        case DHCPS_STATE_NAK://4
#if DHCPS_DEBUG            
            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
#endif
	             send_nak(pmsg_dhcps);
	             break;
			default :
				 break;
        }
#if DHCPS_DEBUG
    	os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
#endif
        pbuf_free(p);
        os_free(pmsg_dhcps);
        pmsg_dhcps = NULL;
}