int check_and_ack(struct dhcpMessage* packet, uint32_t ip) { uint32_t static_ip = 0; /* There is an Static IP for this guy, whether it is requested or not */ if ((static_ip = getIpByMac(server_config.static_leases, packet->chaddr)) != 0) { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:REQUEST ip %x, static ip %x", ip, static_ip); return sendACK(packet, static_ip); } /* requested ip is reserved by a static lease -- if it is himself, situation above match */ if (reservedIp(server_config.static_leases, ip)) { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:REQUEST ip %x is reserved as a static ip", ip); return sendNAK(packet); } /* if some one reserve it */ if ( ip != packet->ciaddr && check_ip(packet, ip) ) { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:REQUEST ip %x already reserved by someone", ip); return sendNAK(packet); } if (ntohl(ip) < ntohl(server_config.start) || ntohl(ip) > ntohl(server_config.end)) { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:REQUEST ip %x is not in the address pool", ip); return sendNAK(packet); } return sendACK(packet, ip); }
//checks if client does not already exist, and if not so, sends ACK message to client int checkClient(int connfd){ struct MessageSBCP joinMessage; struct AttributeSBCP joinMessageAttribute; char temp[16]; int status = 0; read(connfd,(struct MessageSBCP *) &joinMessage,sizeof(joinMessage)); //joinMessageAttribute.payload = (char *)malloc(sizeof(char *) * joinMessage.joinMessageAttribute.length); joinMessageAttribute = joinMessage.attribute[0]; //clients[clientCount].username = (char *)malloc(sizeof(char *) * joinMessage.joinMessageAttribute.length); strcpy(temp, joinMessageAttribute.payload); status = checkUsername(temp); if(status == 1) { printf("\nClient already exists."); sendNAK(connfd, 1); // 1 for client already exists } else { strcpy(clients[clientCount].username, temp); clients[clientCount].fd = connfd; clients[clientCount].clientCount = clientCount; clientCount = clientCount + 1; sendACK(connfd); } return status; }
void NetGuard_DHCPD::packet_in(struct user_data *u_data, int *mode, unsigned int *vlanid, struct tpacket_hdr *h, struct ether_header *eth, struct iphdr *ip, struct tcphdr *tcp, void *data) { if (!security) { ng_logerror_buff(0,"missing Security Module!"); exit(-1); return; } //we only want it once if (*mode == TRAFFIC_INCOMING || *mode == TRAFFIC_OUTGOING ) return; //if (!(*mode == TRAFFIC_OUTGOING )) return; if (eth->ether_type != htons_ETHERTYPE_IP) return; //only ip if (ip->protocol!=IPPROTO_UDP) return; //udp only if (ntohs(tcp->dest) != LISTEN_PORT) return; //only the dhcpd port if ((ip->daddr != zero_ip) && (ip->daddr != ntohl(my_ip)) && (ip->daddr != b_ip)) return; //only send to us //if ((ip->saddr != zero_ip)) return; //only send from zero ip //so we got an dhcp package it seams like dest and port is correct struct dhcpMessage *packet; //void *data2 = data; //it crashes else? packet = (struct dhcpMessage *)((char*)data-12); //TODO check why 12?! crashes? unsigned char *state; //, *hw_addr; unsigned char *server_id; if(htonl(packet->cookie) != MAGIC) { ng_logdebug_spam("ignoring dhcp message with wrong cookie %x",htonl(packet->cookie)); return; } ng_logdebug_spam("got package -- processing"); char *tmpstr = (char*)malloc(5000); sprint_package(tmpstr,vlanid,h,eth,ip,tcp,data); ng_logdebug_spam("%s",tmpstr); free(tmpstr); tmpstr = (char*)malloc(5000); sprint_dhcp_package(tmpstr,packet); ng_logdebug_spam("%s",tmpstr); free(tmpstr); if((state = getOption(packet->options, DHCP_MESSAGE_TYPE)) == NULL) { ng_logdebug_spam("couldnt get option from packet (MSG_TYPE) -- ignoring"); return; } sec_data_idx idx; memcpy(&idx.hw_addr,ð->ether_shost,sizeof(mac_addr)); idx.vlan_id = (*vlanid); user_data *m_u_data = (user_data *)security->get_data(&idx); u_int32_t offerip; //lets see if we can find the ip to offer if (!m_u_data) { ng_logdebug("got client message - but we dont have any known user for that mac %02x:%02x:%02x:%02x:%02x:%02x in vlan %d",printf_mac_params(eth->ether_shost),(*vlanid)); return; //todo look at port etc } offerip = m_u_data->saddr; /* Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Request CLASS Option 77, length 14: "RRAS.Microsoft" Client-ID Option 61, length 17: ether 52:41:53:20:00:14:0b:3b:43:00:00:00:01:00:00:00 Requested-IP Option 50, length 4: 141.30.225.74 Server-ID Option 54, length 4: 141.30.225.1 Hostname Option 12, length 7: "Lins-PC" FQDN Option 81, length 10: [N] "Lins-PC" Vendor-Class Option 60, length 8: "MSFT 5.0" Parameter-Request Option 55, length 12: Subnet-Mask, Domain-Name, Default-Gateway, Domain-Name-Server Netbios-Name-Server, Netbios-Node, Netbios-Scope, Router-Discovery Static-Route, Classless-Static-Route, Classless-Static-Route-Microsoft, Vendor-Option Client-Ethernet-Address 08:10:75:0a:3a:33 Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Request Client-ID Option 61, length 7: ether 08:10:75:0a:3a:33 Hostname Option 12, length 9: "Routerata" Domain-Name Option 15, length 12: "RouterDomain" FQDN Option 81, length 13: "Routerata." Vendor-Class Option 60, length 8: "MSFT 5.0" Requested-IP Option 50, length 4: 141.30.225.42 Subnet-Mask Option 1, length 4: 255.255.255.0 Default-Gateway Option 3, length 4: 141.30.225.1 Domain-Name-Server Option 6, length 8: 141.30.225.3,141.30.66.135 Server-ID Option 54, length 4: 141.30.225.1 Parameter-Request Option 55, length 11: Subnet-Mask, Domain-Name, Default-Gateway, Domain-Name-Server Netbios-Name-Server, Netbios-Node, Netbios-Scope, Router-Discovery Static-Route, Classless-Static-Route-Microsoft, Vendor-Option */ unsigned char *host = getOption(packet->options, 12); unsigned int hostl = getOptionLength(packet->options, 12); unsigned char *fqdn = getOption(packet->options, 15); unsigned int fqdnl = getOptionLength(packet->options, 15); unsigned char *vendor = getOption(packet->options, 60); unsigned int vendorl = getOptionLength(packet->options, 60); unsigned char *dclass = getOption(packet->options, 77); unsigned int dclassl = getOptionLength(packet->options, 77); if (vendor != NULL) { if (strlen((const char*)vendor) == strlen("Adobe Flash Proxy Auto-Discovery")) { if (strncmp("Adobe Flash Proxy Auto-Discovery",(const char*)vendor,strlen("Adobe Flash Proxy Auto-Discovery"))) { ng_logdebug_spam("ignoring Adobe Flash Proxy Auto-Discovery"); return; } } } ng_log_ext_buff(0,500,"offer %s to mac %02x:%02x:%02x:%02x:%02x:%02x - host:%.*s fqdn: %.*s vendor:%.*s class:%.*s", inet_ntoa(*(struct in_addr *)&offerip),printf_mac_params(eth->ether_shost),hostl,host,fqdnl,fqdn,vendorl,vendor,dclassl,dclass); int client_socket; if((client_socket = clientSocket(LISTEN_PORT, SEND_PORT)) == -1) { //syslog(LOG_ERR, "couldn't create client socket -- i'll try again"); return; } struct ifreq intf; //syslog(LOG_INFO, "Binding to interface '%s'\n", interface_name); bzero(&intf, sizeof(intf)); strncpy(intf.ifr_name, interface_name.c_str(), IFNAMSIZ); if (setsockopt(client_socket, SOL_SOCKET, SO_BINDTODEVICE, &intf, sizeof(intf)) < 0) { //syslog(LOG_INFO, "setsockopt(SO_BINDTODEVICE) %d\n", errno); close(client_socket); return; }; switch(state[0]) { case DHCPDISCOVER: ng_logdebug_spam("received DISCOVER"); if(sendOffer(client_socket, packet,offerip,subnet_ip,my_ip,dns_ip1,dns_ip2,wins_ip) == -1) { ng_logerror("send OFFER failed -- ignoring"); } else ng_logdebug_spam("send sendOffer"); break; case DHCPREQUEST: ng_logdebug_spam("received DHCPREQUEST"); //syslog(LOG_INFO,"received REQUEST"); server_id = getOption(packet->options, 0x36); if(server_id == NULL) { ng_logdebug("get option on 0x36 failed! NAKing"); sendNAK(client_socket, packet,my_ip); /* Let's send an offer as well */ if(sendOffer(client_socket, packet,offerip,subnet_ip,my_ip,dns_ip1,dns_ip2,wins_ip) == -1) { ng_logerror("send OFFER failed -- ignoring"); } } else { ng_logdebug_spam("server_id = %02x%02x%02x%02x", server_id[0], server_id[1],server_id[2], server_id[3]); if(memcmp(server_id, (char *)&my_ip, 4) == 0) { ng_logdebug_spam("sending ACK - server_id matched"); if (sendACK(client_socket, packet,offerip,subnet_ip,my_ip,dns_ip1,dns_ip2,wins_ip) == -1) { ng_logdebug("send ACK failed - sending NAK"); sendNAK(client_socket, packet,my_ip); } else { ng_logdebug_spam("send ACK"); } } else { ng_logdebug_spam("sending NAK - server_id missmatch"); sendNAK(client_socket,packet,my_ip); } } break; default: ng_logdebug("unsupported DHCP message (%02x) -- ignoring",state[0]); break; } close(client_socket); }
int main(int argc, char *argv[]) #endif { fd_set rfds; struct timeval tv; int server_socket = -1; int bytes, retval; struct dhcpMessage packet; uint8_t *state; uint8_t *server_id, *requested; uint32_t server_id_align, requested_align; unsigned long timeout_end; struct option_set *option; struct dhcpOfferedAddr *lease; struct dhcpOfferedAddr static_lease; int max_sock; unsigned long num_ips; uint32_t static_lease_ip; memset(&server_config, 0, sizeof(struct server_config_t)); read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]); /* Start the log, sanitize fd's, and write a pid file */ start_log_and_pid("udhcpd", server_config.pidfile); if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } else server_config.lease = LEASE_TIME; /* it is not impossible */ if (server_config.end < server_config.start) { uint32_t tmp_ip = server_config.start; server_config.start = server_config.end ; server_config.end = tmp_ip; } /* Sanity check */ num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1; if (server_config.max_leases > num_ips) { LOG(LOG_ERR, "max_leases value (%lu) not sane, " "setting to %lu instead", server_config.max_leases, num_ips); server_config.max_leases = num_ips; } if (dhcps_shm_init() != 0) return -1; leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr)); memset(leases, 0, server_config.max_leases * sizeof(struct dhcpOfferedAddr)); //read_leases(server_config.lease_file); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp) < 0) return 1; #ifndef UDHCP_DEBUG background(server_config.pidfile); /* hold lock during fork. */ #endif /* Setup the signal pipe */ udhcp_sp_setup(); timeout_end = uptime()/*time(0)*/ + server_config.auto_time; while(1) { /* loop until universe collapses */ if (server_socket < 0) if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { LOG(LOG_ERR, "FATAL: couldn't create server socket, %m"); return 2; } max_sock = udhcp_sp_fd_set(&rfds, server_socket); if (server_config.auto_time) { tv.tv_sec = timeout_end - uptime()/*time(0)*/; tv.tv_usec = 0; } if (!server_config.auto_time || tv.tv_sec > 0) { retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } else retval = 0; /* If we already timed out, fall through */ if (retval == 0) { write_leases(); timeout_end = uptime()/*time(0)*/ + server_config.auto_time; continue; } else if (retval < 0 && errno != EINTR) { DEBUG(LOG_INFO, "error on select"); continue; } switch (udhcp_sp_read(&rfds)) { case SIGUSR1: LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = uptime()/*time(0)*/ + server_config.auto_time; continue; case SIGUSR2: LOG(LOG_INFO, "Received a SIGUSR2, now DHCP SERVER restart"); if (execv(argv[0], argv) == -1) printf("errno:%d\n", errno); /* NEVER reach here except execv failed! */ break; case SIGTERM: LOG(LOG_INFO, "Received a SIGTERM"); return 0; case 0: break; /* no signal */ default: continue; /* signal or error (probably EINTR) */ } if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ if (bytes == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %m, reopening socket"); close(server_socket); server_socket = -1; } continue; } if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); continue; } //printBuf(&packet, sizeof(struct dhcpMessage)); lease = find_lease_by_chaddr(packet.chaddr); if (!lease) { /* Look for a static lease */ static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr); /* found */ if(static_lease_ip) { memcpy(&static_lease.chaddr, &packet.chaddr, 16); static_lease.yiaddr = static_lease_ip; static_lease.expires = 0; lease = &static_lease; } /* else { lease = find_lease_by_chaddr(packet.chaddr); } */ } switch (state[0]) { case DHCPDISCOVER: //DEBUG(LOG_INFO,"received DISCOVER"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Recv DISCOVER from %02X:%02X:%02X:%02X:%02X:%02X", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); if (sendOffer(&packet) < 0) { LOG(LOG_ERR, "send OFFER failed"); } break; case DHCPREQUEST: //DEBUG(LOG_INFO, "received REQUEST"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Recv REQUEST from %02X:%02X:%02X:%02X:%02X:%02X", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); requested = get_option(&packet, DHCP_REQUESTED_IP); server_id = get_option(&packet, DHCP_SERVER_ID); if (requested) memcpy(&requested_align, requested, 4); if (server_id) memcpy(&server_id_align, server_id, 4); if (lease) { if (server_id) { /* SELECTING State */ DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align)); if (server_id_align == server_config.server && requested && requested_align == lease->yiaddr) { sendACK(&packet, lease->yiaddr); } else { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Wrong Server id or request an invalid ip"); sendNAK(&packet); } } else { if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Server id not found and request an invalid ip"); sendNAK(&packet); } } else { /* RENEWING or REBINDING State */ if (lease->yiaddr == packet.ciaddr) sendACK(&packet, lease->yiaddr); else { /* don't know what to do!!!! */ msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Server id and requested ip not found"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:%x %x", lease->yiaddr, packet.ciaddr); sendNAK(&packet); } } } /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ } else if (requested) { /* INIT-REBOOT State */ if ((lease = find_lease_by_yiaddr(requested_align))) { /* Requested IP already reserved by other one */ if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); check_and_ack(&packet, requested_align); /* make some contention for this address */ } else /* still reserved by someone */ { msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:REQUEST ip %x already reserved by %02X:%02X:%02X:%02X:%02X:%02X", requested_align, lease->chaddr[0], lease->chaddr[1], lease->chaddr[2], lease->chaddr[3], lease->chaddr[4], lease->chaddr[5]); sendNAK(&packet); } } else /*if (requested_align < server_config.start || requested_align > server_config.end)*/ { check_and_ack(&packet, requested_align); } /* else remain silent */ } else { /* error state, just reply NAK modified by tiger 20090927 */ sendNAK(&packet); } break; case DHCPDECLINE: //DEBUG(LOG_INFO,"received DECLINE"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Recv DECLINE from %02X:%02X:%02X:%02X:%02X:%02X", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); if (lease) { memset(lease->chaddr, 0, 16); lease->expires = uptime()/*time(0)*/ + server_config.decline_time; } break; case DHCPRELEASE: //DEBUG(LOG_INFO,"received RELEASE"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Recv RELEASE from %02X:%02X:%02X:%02X:%02X:%02X", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); if (lease) { /* Delete the lease, lsz 080221 */ #if 1 memset(lease, 0, sizeof(struct dhcpOfferedAddr)); #else lease->expires = uptime()/*time(0)*/; #endif } break; case DHCPINFORM: //DEBUG(LOG_INFO,"received INFORM"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPS:Recv INFORM from %02X:%02X:%02X:%02X:%02X:%02X", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); send_inform(&packet); break; default: LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); } } return 0; }
int udhcpd_main(int argc, char **argv) { fd_set rfds; struct timeval tv; int server_socket = -1, bytes, retval, max_sock; struct dhcpMessage packet; uint8_t *state, *server_id, *requested; uint32_t server_id_align, requested_align, static_lease_ip; unsigned timeout_end; unsigned num_ips; unsigned opt; struct option_set *option; struct dhcpOfferedAddr *lease, static_lease; opt = getopt32(argv, "fS"); argv += optind; if (!(opt & 1)) { /* no -f */ bb_daemonize_or_rexec(0, argv); logmode &= ~LOGMODE_STDIO; } if (opt & 2) { /* -S */ openlog(applet_name, LOG_PID, LOG_LOCAL0); logmode |= LOGMODE_SYSLOG; } /* Would rather not do read_config before daemonization - * otherwise NOMMU machines will parse config twice */ read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); /* Make sure fd 0,1,2 are open */ bb_sanitize_stdio(); /* Equivalent of doing a fflush after every \n */ setlinebuf(stdout); /* Create pidfile */ write_pidfile(server_config.pidfile); /* if (!..) bb_perror_msg("cannot create pidfile %s", pidfile); */ bb_info_msg("%s (v"BB_VER") started", applet_name); option = find_option(server_config.options, DHCP_LEASE_TIME); server_config.lease = LEASE_TIME; if (option) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } /* Sanity check */ num_ips = server_config.end_ip - server_config.start_ip + 1; if (server_config.max_leases > num_ips) { bb_error_msg("max_leases=%u is too big, setting to %u", (unsigned)server_config.max_leases, num_ips); server_config.max_leases = num_ips; } leases = xzalloc(server_config.max_leases * sizeof(*leases)); read_leases(server_config.lease_file); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp)) { retval = 1; goto ret; } /* Setup the signal pipe */ udhcp_sp_setup(); timeout_end = monotonic_sec() + server_config.auto_time; while (1) { /* loop until universe collapses */ if (server_socket < 0) { server_socket = listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server_config.interface); } max_sock = udhcp_sp_fd_set(&rfds, server_socket); if (server_config.auto_time) { tv.tv_sec = timeout_end - monotonic_sec(); tv.tv_usec = 0; } retval = 0; if (!server_config.auto_time || tv.tv_sec > 0) { retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } if (retval == 0) { write_leases(); timeout_end = monotonic_sec() + server_config.auto_time; continue; } if (retval < 0 && errno != EINTR) { DEBUG("error on select"); continue; } switch (udhcp_sp_read(&rfds)) { case SIGUSR1: bb_info_msg("Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = monotonic_sec() + server_config.auto_time; continue; case SIGTERM: bb_info_msg("Received a SIGTERM"); goto ret0; case 0: break; /* no signal */ default: continue; /* signal or error (probably EINTR) */ } bytes = udhcp_recv_packet(&packet, server_socket); /* this waits for a packet - idle */ if (bytes < 0) { if (bytes == -1 && errno != EINTR) { DEBUG("error on read, %s, reopening socket", strerror(errno)); close(server_socket); server_socket = -1; } continue; } state = get_option(&packet, DHCP_MESSAGE_TYPE); if (state == NULL) { bb_error_msg("cannot get option from packet, ignoring"); continue; } /* Look for a static lease */ static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr); if (static_lease_ip) { bb_info_msg("Found static lease: %x", static_lease_ip); memcpy(&static_lease.chaddr, &packet.chaddr, 16); static_lease.yiaddr = static_lease_ip; static_lease.expires = 0; lease = &static_lease; } else { lease = find_lease_by_chaddr(packet.chaddr); } switch (state[0]) { case DHCPDISCOVER: DEBUG("Received DISCOVER"); if (sendOffer(&packet) < 0) { bb_error_msg("send OFFER failed"); } /* circle test Stat. add by wangpu begin */ g_offercount ++; printf("Circle test: [DHCPS] send OFFER packet num:[%d]\n",g_offercount); memset(g_acCmd,0,sizeof(g_acCmd)); memset(g_interface,0,sizeof(g_interface)); sprintf(g_interface,"%s",server_config.interface); sprintf(g_acCmd,"echo %d > /var/circle/%s",g_offercount,g_interface); system(g_acCmd); /* circle test Stat. add by wangpu end */ break; case DHCPREQUEST: DEBUG("received REQUEST"); #if 0 /* ?¡¤??2a¨º? add by wangpu begin */ g_offercount ++; printf("Circle test: [DHCPS] send OFFER packet num:[%d]\n",g_offercount); memset(g_acCmd,0,sizeof(g_acCmd)); memset(g_interface,0,sizeof(g_interface)); sprintf(g_interface,"%s",server_config.interface); sprintf(g_acCmd,"echo %d > /var/circle/%s",g_offercount,g_interface); system(g_acCmd); /* ?¡¤??2a¨º? add by wangpu begin */ #endif requested = get_option(&packet, DHCP_REQUESTED_IP); server_id = get_option(&packet, DHCP_SERVER_ID); if (requested) memcpy(&requested_align, requested, 4); if (server_id) memcpy(&server_id_align, server_id, 4); if (lease) { if (server_id) { /* SELECTING State */ DEBUG("server_id = %08x", ntohl(server_id_align)); if (server_id_align == server_config.server && requested && requested_align == lease->yiaddr ) { sendACK(&packet, lease->yiaddr); } } else if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else sendNAK(&packet); } else if (lease->yiaddr == packet.ciaddr) { /* RENEWING or REBINDING State */ sendACK(&packet, lease->yiaddr); } else { /* don't know what to do!!!! */ sendNAK(&packet); } /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ } else if (requested) { /* INIT-REBOOT State */ lease = find_lease_by_yiaddr(requested_align); if (lease) { if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); /* make some contention for this address */ } else sendNAK(&packet); } else { uint32_t r = ntohl(requested_align); if (r < server_config.start_ip || r > server_config.end_ip ) { sendNAK(&packet); } /* else remain silent */ } } else { /* RENEWING or REBINDING State */ } break; case DHCPDECLINE: DEBUG("Received DECLINE"); if (lease) { memset(lease->chaddr, 0, 16); lease->expires = time(0) + server_config.decline_time; } break; case DHCPRELEASE: DEBUG("Received RELEASE"); if (lease) lease->expires = time(0); break; case DHCPINFORM: DEBUG("Received INFORM"); send_inform(&packet); break; default: bb_info_msg("Unsupported DHCP message (%02x) - ignoring", state[0]); } } ret0: retval = 0; ret: /*if (server_config.pidfile) - server_config.pidfile is never NULL */ remove_pidfile(server_config.pidfile); return retval; }
int main(int argc, char *argv[]) #endif { fd_set rfds; struct timeval tv; int server_socket = -1; int bytes, retval; struct dhcpMessage packet; uint8_t *state; uint8_t *server_id, *requested; uint8_t *hostname; uint32_t server_id_align, requested_align; unsigned long timeout_end; struct option_set *option; struct dhcpOfferedAddr *lease; struct dhcpOfferedAddr static_lease; int max_sock; unsigned long num_ips; uint32_t static_lease_ip; memset(&server_config, 0, sizeof(struct server_config_t)); read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]); read_config_static_leases(DHCPD_STATIC_LEASES_FILE); /* Start the log, sanitize fd's, and write a pid file */ start_log_and_pid("udhcpd", server_config.pidfile); if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } else server_config.lease = LEASE_TIME; /* Sanity check */ num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1; if (server_config.max_leases > num_ips) { // LOG(LOG_ERR, "max_leases value (%lu) not sane, " // "setting to %lu instead", // server_config.max_leases, num_ips); server_config.max_leases = num_ips; } leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr)); read_leases(server_config.lease_file); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp) < 0) return 1; #ifndef UDHCP_DEBUG background(server_config.pidfile); /* hold lock during fork. */ #endif /* Setup the signal pipe */ udhcp_sp_setup(); timeout_end = time(0) + server_config.auto_time; while(1) { /* loop until universe collapses */ if (server_socket < 0) if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { LOG(LOG_ERR, "FATAL: couldn't create server socket, %m"); return 2; } max_sock = udhcp_sp_fd_set(&rfds, server_socket); if (server_config.auto_time) { tv.tv_sec = timeout_end - time(0); tv.tv_usec = 0; } if (!server_config.auto_time || tv.tv_sec > 0) { retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } else retval = 0; /* If we already timed out, fall through */ if (retval == 0) { write_leases(); timeout_end = time(0) + server_config.auto_time; continue; } else if (retval < 0 && errno != EINTR) { DEBUG(LOG_INFO, "error on select"); continue; } switch (udhcp_sp_read(&rfds)) { case SIGUSR1: LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = time(0) + server_config.auto_time; continue; case SIGTERM: LOG(LOG_INFO, "Received a SIGTERM"); return 0; case 0: break; /* no signal */ default: continue; /* signal or error (probably EINTR) */ } if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ if (bytes == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %m, reopening socket"); close(server_socket); server_socket = -1; } continue; } if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); continue; } /* Look for a static lease */ static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr); if(static_lease_ip) { printf("Found static lease: %x\n", static_lease_ip); memcpy(&static_lease.chaddr, &packet.chaddr, 16); static_lease.yiaddr = static_lease_ip; static_lease.expires = 0; lease = &static_lease; } else { lease = find_lease_by_chaddr(packet.chaddr); } switch (state[0]) { case DHCPDISCOVER: DEBUG(LOG_INFO,"received DISCOVER"); if (sendOffer(&packet) < 0) { LOG(LOG_ERR, "send OFFER failed"); } break; case DHCPREQUEST: DEBUG(LOG_INFO, "received REQUEST"); requested = get_option(&packet, DHCP_REQUESTED_IP); server_id = get_option(&packet, DHCP_SERVER_ID); hostname = get_option(&packet, DHCP_HOST_NAME); if (requested) memcpy(&requested_align, requested, 4); if (server_id) memcpy(&server_id_align, server_id, 4); if (lease) { if (server_id) { /* SELECTING State */ DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align)); if (server_id_align == server_config.server && requested && requested_align == lease->yiaddr) { sendACK(&packet, lease->yiaddr); } } else { if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else sendNAK(&packet); } else { /* RENEWING or REBINDING State */ if (lease->yiaddr == packet.ciaddr) sendACK(&packet, lease->yiaddr); else { /* don't know what to do!!!! */ sendNAK(&packet); } } } if (hostname) { bytes = hostname[-1]; if (bytes >= (int) sizeof(lease->hostname)) bytes = sizeof(lease->hostname) - 1; strncpy(lease->hostname, hostname, bytes); lease->hostname[bytes] = '\0'; } else lease->hostname[0] = '\0'; /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ } else if (requested) { /* INIT-REBOOT State */ if ((lease = find_lease_by_yiaddr(requested_align))) { if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); /* make some contention for this address */ } else sendNAK(&packet); } else if (requested_align < server_config.start || requested_align > server_config.end) { sendNAK(&packet); } /* else remain silent */ } else { /* RENEWING or REBINDING State */ } break; case DHCPDECLINE: DEBUG(LOG_INFO,"received DECLINE"); if (lease) { memset(lease->chaddr, 0, 16); lease->expires = time(0) + server_config.decline_time; } break; case DHCPRELEASE: DEBUG(LOG_INFO,"received RELEASE"); if (lease) lease->expires = time(0); break; case DHCPINFORM: DEBUG(LOG_INFO,"received INFORM"); send_inform(&packet); break; default: LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); } } return 0; }
RPH_TYPE CRemoteProtocolHandler::readType() { m_type = RPHT_NONE; in_addr address; unsigned int port; int length = m_socket.read(m_inBuffer, BUFFER_LENGTH, address, port); if (length <= 0) return m_type; // CUtils::dump(wxT("Incoming"), m_inBuffer, length); if (::memcmp(m_inBuffer, "LIN", 3U) == 0) { m_loggedIn = false; m_address = address; m_port = port; m_type = RPHT_LOGIN; return m_type; } if (address.s_addr == inet_addr("127.0.0.1")) { if (::memcmp(m_inBuffer, "LKS", 3U) == 0) { m_inLength = length; m_type = RPHT_LINKSCR; return m_type; } } if (m_loggedIn) { if (address.s_addr != m_address.s_addr || port != m_port) { sendNAK(wxT("You are not logged in")); return m_type; } } m_inLength = length; if (::memcmp(m_inBuffer, "SHA", 3U) == 0) { if (m_loggedIn) { sendNAK(wxT("Someone is already logged in")); return m_type; } m_type = RPHT_HASH; return m_type; } else if (::memcmp(m_inBuffer, "GCS", 3U) == 0) { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_CALLSIGNS; return m_type; } else if (::memcmp(m_inBuffer, "GRP", 3U) == 0) { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_REPEATER; return m_type; } else if (::memcmp(m_inBuffer, "GSN", 3U) == 0) { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_STARNET; return m_type; } else if (::memcmp(m_inBuffer, "LNK", 3U) == 0) { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_LINK; return m_type; } else if (::memcmp(m_inBuffer, "UNL", 3U) == 0) { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_UNLINK; return m_type; } else if (::memcmp(m_inBuffer, "LGO", 3U) == 0) { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_LOGOFF; return m_type; } else if (::memcmp(m_inBuffer, "LOG", 3U) == 0) { if (!m_loggedIn) return m_type; m_type = RPHT_LOGOUT; return m_type; } else { if (!m_loggedIn) { sendNAK(wxT("You are not logged in")); return m_type; } m_type = RPHT_UNKNOWN; return m_type; } }
int main(int argc, char *argv[]) #endif { fd_set rfds; struct timeval tv; int server_socket = -1; int bytes, retval; struct dhcpMessage packet; unsigned char *state; unsigned char *server_id, *requested, *hostname; u_int32_t server_id_align, requested_align; unsigned long timeout_end; struct option_set *option; struct dhcpOfferedAddr *lease; int pid_fd; int max_sock; int sig; /* DD-WRT (belanger) : ignore signals until we're ready */ signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); OPEN_LOG("udhcpd"); LOG(LOG_INFO, "udhcp server (v%s) started", VERSION); memset(&server_config, 0, sizeof(struct server_config_t)); if (argc < 2) read_config(DHCPD_CONF_FILE); else read_config(argv[1]); pid_fd = pidfile_acquire(server_config.pidfile); pidfile_write_release(pid_fd); if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } else server_config.lease = LEASE_TIME; leases = malloc(sizeof(struct dhcpOfferedAddr) * server_config.max_leases); memset(leases, 0, sizeof(struct dhcpOfferedAddr) * server_config.max_leases); read_leases(server_config.lease_file); read_statics(server_config.statics_file); /* DD-WRT (belanger) : write leases now */ write_leases(); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp) < 0) exit_server(1); #ifndef DEBUGGING pid_fd = pidfile_acquire(server_config.pidfile); /* hold lock during fork. */ if (daemon(0, 0) == -1) { perror("fork"); exit_server(1); } pidfile_write_release(pid_fd); #endif socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe); signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); timeout_end = get_time(0) + server_config.auto_time; while(1) { /* loop until universe collapses */ if (server_socket < 0) if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { LOG(LOG_ERR, "FATAL: couldn't create server socket, %s", strerror(errno)); exit_server(0); } FD_ZERO(&rfds); FD_SET(server_socket, &rfds); FD_SET(signal_pipe[0], &rfds); if (server_config.auto_time) { tv.tv_sec = timeout_end - get_time(0); tv.tv_usec = 0; } if (!server_config.auto_time || tv.tv_sec > 0) { max_sock = server_socket > signal_pipe[0] ? server_socket : signal_pipe[0]; retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } else retval = 0; /* If we already timed out, fall through */ if (retval == 0) { write_leases(); timeout_end = get_time(0) + server_config.auto_time; continue; } else if (retval < 0 && errno != EINTR) { DEBUG(LOG_INFO, "error on select"); continue; } if (FD_ISSET(signal_pipe[0], &rfds)) { if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) continue; /* probably just EINTR */ switch (sig) { case SIGUSR1: LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = get_time(0) + server_config.auto_time; continue; case SIGUSR2: LOG(LOG_INFO, "Received a SIGUSR2"); delete_leases(); continue; case SIGHUP: LOG(LOG_INFO, "Received a SIGHUP"); read_leases(server_config.lease_file); read_statics(server_config.statics_file); continue; case SIGTERM: LOG(LOG_INFO, "Received a SIGTERM"); exit_server(0); } } if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ if (bytes == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno)); close(server_socket); server_socket = -1; } continue; } if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); continue; } hostname = get_option(&packet, DHCP_HOST_NAME); /* ADDME: look for a static lease */ /* If a hostname is supplied, and that hostname is a static lease, and that static lease has an FF:FF:FF:FF:FF:FF MAC address, then use that entry. */ if ( NULL == hostname || NULL == (lease = find_lease_by_hostname(hostname)) || (lease->expires != EXPIRES_NEVER) || 0 != memcmp(lease->chaddr, MAC_BCAST_ADDR, strlen(MAC_BCAST_ADDR))) { /* Otherwise, look up the table using the supplied MAC address. */ lease = find_lease_by_chaddr(packet.chaddr); } switch (state[0]) { case DHCPDISCOVER: LOG(LOG_INFO,"received DISCOVER from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor if (sendOffer(&packet, lease) < 0) { LOG(LOG_ERR, "send OFFER failed"); } break; case DHCPREQUEST: requested = get_option(&packet, DHCP_REQUESTED_IP); server_id = get_option(&packet, DHCP_SERVER_ID); if (requested) memcpy(&requested_align, requested, 4); if (server_id) memcpy(&server_id_align, server_id, 4); if (requested) { struct in_addr addr; addr.s_addr = requested_align; LOG(LOG_INFO, "received REQUEST for %s from %02x:%02x:%02x:%02x:%02x:%02x", inet_ntoa(addr), packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); } else { LOG(LOG_INFO, "received REQUEST from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); } if (lease) { /*ADDME: or static lease */ if (server_id) { /* SELECTING State */ DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align)); if (server_id_align == server_config.server && requested && requested_align == lease->yiaddr) { sendACK(&packet, lease->yiaddr); } else sendNAK(&packet); //Sveasoft - shouldn't we let them know we don't like the request? } else { if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else sendNAK(&packet); } else { /* RENEWING or REBINDING State */ if (lease->yiaddr == packet.ciaddr) sendACK(&packet, lease->yiaddr); // else if (!packet.ciaddr) /* Accept an invalid request in RENEWING state, where the ciaddr should be set, but is not. */ /* e.g. Linksys Print Server */ // sendACK(&packet, lease->yiaddr); //note: let's not support broken stuff - Sveasoft 2005-01-19 else { /* don't know what to do!!!! */ sendNAK(&packet); } } } if (lease->expires != EXPIRES_NEVER) { /* Don't change hostname of static leases */ if (hostname) { bytes = hostname[-1]; if (bytes >= (int) sizeof(lease->hostname)) bytes = sizeof(lease->hostname) - 1; strncpy(lease->hostname, hostname, bytes); lease->hostname[bytes] = '\0'; } else lease->hostname[0] = '\0'; } /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ sendNAK(&packet); // by honor } else if (requested) { /* INIT-REBOOT State */ if ((lease = find_lease_by_yiaddr(requested_align))) { if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); /* make some contention for this address */ } else sendNAK(&packet); } else if (requested_align < server_config.start || requested_align > server_config.end) { sendNAK(&packet); } else { sendNAK(&packet); } } else if (packet.ciaddr) { /* RENEWING or REBINDING State */ sendNAK(&packet); } break; case DHCPDECLINE: LOG(LOG_INFO,"received DECLINE from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor if (lease && lease->expires != EXPIRES_NEVER) { memset(lease->chaddr, 0, 16); lease->expires = get_time(0) + server_config.decline_time; } break; case DHCPRELEASE: LOG(LOG_INFO,"received RELEASE from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor if (lease && lease->expires != EXPIRES_NEVER) lease->expires = get_time(0); break; case DHCPINFORM: LOG(LOG_INFO,"received INFORM from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor send_inform(&packet); break; default: LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); } } return 0; }
/* * int linestream_receiveFrame(unsigned char *dest, unsigned maxsize) * receive a full frame * */ int linestream_receiveFrame(unsigned char *dest, unsigned maxsize) { unsigned char *dptr = dest; unsigned int bIn; unsigned int ctrl = 0; unsigned int checksum=0; state = CONTROL; do { bIn = readData(); if (bIn==HDLC_escapeFlag) { unEscaping=1; continue; } if (bIn==HDLC_frameFlag && !unEscaping) { if (inFrame) { inFrame = 0; /* Check frame type */ if (state==CONTROL) return -1; /* Error, no data */ state = CONTROL; /* Checksum computation */ if (checksum!=0) { continue; } if (!(ctrl & 0x80)) { /* Control frame */ handleControl(ctrl,dest, dptr-dest); if (ctrl==HDLC_Control_Reset) { /* Reset Ack frame */ *--dptr; } continue; } else { /* Data frame */ if ( (ctrl & 0x7) != rxSeq ) { /* out of order */ sendNAK(); continue; } } /* Ack this frame */ rxSeq++; rxSeq &= 0x7; sendACK(); // removing chk *--dptr = '\0'; return dptr - dest; } else { /* Beginning of packet */ inFrame = 1; state = CONTROL; checksum=0xaa; } } else { if (!inFrame) continue; if (unEscaping) { bIn^=HDLC_escapeXOR; unEscaping=0; } checksum^=bIn; /* State processing */ switch (state) { case CONTROL: ctrl = bIn; state=DATA; break; case DATA: if (maxsize-- == 0) { return -1; /* Overflow */ } *dptr++=bIn; break; } } } while (1); }
int main(int argc, char *argv[]) #endif { fd_set rfds; struct timeval tv; int server_socket = -1; int bytes, retval; struct dhcpMessage packet; unsigned char *state; unsigned char *server_id, *requested, *hostname; u_int32_t server_id_align, requested_align; unsigned long timeout_end; struct option_set *option; struct dhcpOfferedAddr *lease; int pid_fd; int max_sock; int sig; OPEN_LOG("udhcpd"); LOG(LOG_INFO, "udhcp server (v%s) started", VERSION); memset(&server_config, 0, sizeof(struct server_config_t)); if (argc < 2) read_config(DHCPD_CONF_FILE); else read_config(argv[1]); pid_fd = pidfile_acquire(server_config.pidfile); pidfile_write_release(pid_fd); if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } else server_config.lease = LEASE_TIME; leases = malloc(sizeof(struct dhcpOfferedAddr) * server_config.max_leases); memset(leases, 0, sizeof(struct dhcpOfferedAddr) * server_config.max_leases); // Added by Joey to load static lease if (argc>=3) { load_leases(argv[2]); } read_leases(server_config.lease_file); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp) < 0) exit_server(1); #ifndef DEBUGGING pid_fd = pidfile_acquire(server_config.pidfile); /* hold lock during fork. */ if (daemon(0, 0) == -1) { perror("fork"); exit_server(1); } pidfile_write_release(pid_fd); #endif /* ensure that stdin/stdout/stderr are never returned by pipe() */ if (fcntl(STDIN_FILENO, F_GETFL) == -1) (void) open("/dev/null", O_RDONLY); if (fcntl(STDOUT_FILENO, F_GETFL) == -1) (void) open("/dev/null", O_WRONLY); if (fcntl(STDERR_FILENO, F_GETFL) == -1) (void) open("/dev/null", O_WRONLY); /* setup signal handlers */ pipe(signal_pipe); signal(SIGUSR1, signal_handler); signal(SIGTERM, signal_handler); timeout_end = uptime() + server_config.auto_time; while(1) { /* loop until universe collapses */ if (server_socket < 0) if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { LOG(LOG_ERR, "FATAL: couldn't create server socket, %s", strerror(errno)); exit_server(0); } FD_ZERO(&rfds); FD_SET(server_socket, &rfds); FD_SET(signal_pipe[0], &rfds); if (server_config.auto_time) { tv.tv_sec = timeout_end - uptime(); tv.tv_usec = 0; } if (!server_config.auto_time || tv.tv_sec > 0) { max_sock = server_socket > signal_pipe[0] ? server_socket : signal_pipe[0]; retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } else retval = 0; /* If we already timed out, fall through */ if (retval == 0) { write_leases(); timeout_end = uptime() + server_config.auto_time; continue; } else if (retval < 0 && errno != EINTR) { DEBUG(LOG_INFO, "error on select"); continue; } if (FD_ISSET(signal_pipe[0], &rfds)) { if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) continue; /* probably just EINTR */ switch (sig) { case SIGUSR1: LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = uptime() + server_config.auto_time; continue; case SIGTERM: LOG(LOG_INFO, "Received a SIGTERM"); exit_server(0); } } if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ if (bytes == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno)); close(server_socket); server_socket = -1; } continue; } if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); continue; } server_id = get_option(&packet, DHCP_SERVER_ID); if (server_id) { memcpy(&server_id_align, server_id, 4); if (server_id_align != server_config.server) { /* client talks to somebody else */ DEBUG(LOG_INFO,"server ID %08x doesn't match, ignoring", ntohl(server_id_align)); continue; } } /* ADDME: look for a static lease */ lease = find_lease_by_chaddr(packet.chaddr); switch (state[0]) { case DHCPDISCOVER: DEBUG(LOG_INFO,"received DISCOVER"); if (sendOffer(&packet) < 0) { LOG(LOG_ERR, "send OFFER failed"); } break; case DHCPREQUEST: DEBUG(LOG_INFO, "received REQUEST"); requested = get_option(&packet, DHCP_REQUESTED_IP); hostname = get_option(&packet, DHCP_HOST_NAME); if (requested) memcpy(&requested_align, requested, 4); if (lease) { /*ADDME: or static lease */ if (server_id) { /* SELECTING State */ if (requested && requested_align == lease->yiaddr) { sendACK(&packet, lease->yiaddr); } } else { if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else sendNAK(&packet); } else { /* RENEWING or REBINDING State */ if (lease->yiaddr == packet.ciaddr) sendACK(&packet, lease->yiaddr); else { /* don't know what to do!!!! */ sendNAK(&packet); } } } if (hostname) { bytes = hostname[-1]; if (bytes >= (int) sizeof(lease->hostname)) bytes = sizeof(lease->hostname) - 1; strncpy(lease->hostname, hostname, bytes); lease->hostname[bytes] = '\0'; if (!is_valid_hostname(lease->hostname)) lease->hostname[0] = '\0'; } else lease->hostname[0] = '\0'; /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ if (requested) sendNAK(&packet); } else if (requested) { /* INIT-REBOOT State */ if ((lease = find_lease_by_yiaddr(requested_align))) { if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); /* make some contention for this address */ } else sendNAK(&packet); } else if (requested_align < server_config.start || requested_align > server_config.end) { sendNAK(&packet); } else { sendNAK(&packet); } } else if (packet.ciaddr) { /* RENEWING or REBINDING State */ sendNAK(&packet); } break; case DHCPDECLINE: DEBUG(LOG_INFO,"received DECLINE"); if (lease) { memset(lease->chaddr, 0, 16); lease->expires = uptime() + server_config.decline_time; } break; case DHCPRELEASE: DEBUG(LOG_INFO,"received RELEASE"); if (lease) lease->expires = uptime(); break; case DHCPINFORM: DEBUG(LOG_INFO,"received INFORM"); send_inform(&packet); break; default: LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); } } return 0; }