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; }
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); } }
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; }
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; }