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; /* 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); 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); } } } /* 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; }
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 CXSPAsyncSocket::ListenSocket() { return listen_socket(&m_socket); }
int main(int argc, char**argv) { int msock; /* master socket */ int ssock; /* slave socket */ int portno; /* port to listen on */ socklen_t clientlen; /* byte size of client's address */ struct sockaddr_in serveraddr; /* server's addr */ struct sockaddr_in clientaddr; /* client addr */ char buf[400]; /* message buffer */ char *hostaddrp; /* dotted decimal host addr string */ int optval; /* flag value for setsockopt */ int n; /* message byte size */ if (argc != 2) { fprintf(stderr, "usage: %s <port>\n", argv[0]); exit(1); } portno = atoi(argv[1]); msock = create_socket(AF_207TCP, SOCK_207STREAM, IPPROTO_207TCP); if (msock < 0) perror("ERROR opening socket"); bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons((unsigned short)portno); if (bind_socket(msock, (struct sockaddr_in *) &serveraddr, sizeof(serveraddr)) < 0) perror("ERROR on binding"); while (1) { if (listen_socket(msock, 5) < 0) perror("ERROR on listen"); clientlen = sizeof(clientaddr); ssock = accept_connection(msock, (struct sockaddr_in *) &clientaddr, clientlen); if (ssock < 0) perror("ERROR on accept"); pid_t childpid=fork(); if (childpid == 0) { //close(ssock); //int abc; //scanf("%d",&abc); char buffer[4000],converted[4000]; int nr = recv_data(ssock,buffer,sizeof(buffer),0); int i; for(i=0;i<nr;i++) converted[i]= toupper(buffer[i]); printf("\nConverted %s",converted); printf("\n\n"); send_data(ssock,converted,sizeof(converted),0); //close_connection(ssock); nr = recv_data(ssock,buffer,sizeof(buffer),0); exit(0); } } // int i; // for(i=0;i<3000;i++) // printf("\nData Recieved: %d\n%s",buffer[i]); }
int main(int argc, char *argv[]) #endif { char *temp, *message; unsigned long t1 = 0, t2 = 0, xid = 0; unsigned long start = 0, lease; fd_set rfds; int fd, retval; struct timeval tv; int c, len; struct ifreq ifr; struct dhcpMessage packet; struct in_addr temp_addr; int pid_fd; static struct option options[] = { {"clientid", required_argument, 0, 'c'}, {"foreground", no_argument, 0, 'f'}, {"hostname", required_argument, 0, 'H'}, {"help", no_argument, 0, 'h'}, {"interface", required_argument, 0, 'i'}, {"now", no_argument, 0, 'n'}, {"pidfile", required_argument, 0, 'p'}, {"quit", no_argument, 0, 'q'}, {"request", required_argument, 0, 'r'}, {"script", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; /* get options */ while (1) { int option_index = 0; // brcm c = getopt_long(argc, argv, "c:fH:hi:np:qr:s:d:v", options, &option_index); if (c == -1) break; switch (c) { case 'c': len = strlen(optarg) > 255 ? 255 : strlen(optarg); if (client_config.clientid) free(client_config.clientid); client_config.clientid = malloc(len + 2); client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; client_config.clientid[OPT_LEN] = len; strncpy(client_config.clientid + 2, optarg, len); break; case 'f': client_config.foreground = 1; break; case 'H': len = strlen(optarg) > 255 ? 255 : strlen(optarg); if (client_config.hostname) free(client_config.hostname); client_config.hostname = malloc(len + 2); client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; client_config.hostname[OPT_LEN] = len; strncpy(client_config.hostname + 2, optarg, len); break; case 'h': print_usage(); return 0; case 'i': client_config.interface = optarg; // brcm strcpy(session_path, optarg); break; case 'n': client_config.abort_if_no_lease = 1; break; case 'p': client_config.pidfile = optarg; break; case 'q': client_config.quit_after_lease = 1; break; case 'r': requested_ip = inet_addr(optarg); break; // brcm case 'd': strcpy(vendor_class_id, optarg); break; case 's': client_config.script = optarg; break; case 'v': printf("udhcpcd, version %s\n\n", VERSION); break; } } // brcm if (strlen(session_path) > 0) { sprintf(status_path, "%s/%s/%s", _PATH_WAN_DIR, session_path, _PATH_MSG); sprintf(pid_path, "%s/%s/%s", _PATH_WAN_DIR, session_path, _PATH_PID); } OPEN_LOG("udhcpc"); LOG(LOG_INFO, "udhcp client (v%s) started", VERSION); pid_fd = pidfile_acquire(client_config.pidfile); pidfile_write_release(pid_fd); if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) { strcpy(ifr.ifr_name, client_config.interface); if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex); client_config.ifindex = ifr.ifr_ifindex; } else { LOG(LOG_ERR, "SIOCGIFINDEX failed! %s", strerror(errno)); exit_client(1); } if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) { memcpy(client_config.arp, ifr.ifr_hwaddr.sa_data, 6); DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", client_config.arp[0], client_config.arp[1], client_config.arp[2], client_config.arp[3], client_config.arp[4], client_config.arp[5]); } else { LOG(LOG_ERR, "SIOCGIFHWADDR failed! %s", strerror(errno)); exit_client(1); } } else { LOG(LOG_ERR, "socket failed! %s", strerror(errno)); exit_client(1); } close(fd); fd = -1; /* setup signal handlers */ signal(SIGUSR1, renew_requested); signal(SIGUSR2, release_requested); signal(SIGTERM, terminate); state = INIT_SELECTING; // brcm // run_script(NULL, "deconfig"); // brcm setStatus(0); for (;;) { if (fd > 0) { close(fd); fd = -1; } if (listen_mode == LISTEN_KERNEL) { if ((fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface)) < 0) { LOG(LOG_ERR, "couldn't create server socket -- au revoir"); exit_client(0); } } else if (listen_mode == LISTEN_RAW) { if ((fd = raw_socket(client_config.ifindex)) < 0) { LOG(LOG_ERR, "couldn't create raw socket -- au revoir"); exit_client(0); } } else fd = -1; tv.tv_sec = timeout - time(0); tv.tv_usec = 0; FD_ZERO(&rfds); if (listen_mode) FD_SET(fd, &rfds); if (tv.tv_sec > 0) retval = select(fd + 1, &rfds, NULL, NULL, &tv); else retval = 0; /* If we already timed out, fall through */ //printf("state: %d, retval: %d \n", state, retval); if (retval == 0) { /* timeout dropped to zero */ switch (state) { case INIT_SELECTING: #if 0 // brcm setStatus(0); if (packet_num < 3) { if (packet_num == 0) xid = random_xid(); /* send discover packet */ send_discover(xid, requested_ip); /* broadcast */ timeout = time(0) + ((packet_num == 2) ? 10 : 2); packet_num++; } else { if (client_config.abort_if_no_lease) { LOG(LOG_INFO, "No lease, failing."); exit_client(1); } /* wait to try again */ packet_num = 0; timeout = time(0) + 60; } break; #else // brcm setStatus(0); if (packet_num < 4) { //if(dis_seq == 1) //{ // timeout = time(0) + 64; //} //else //{ if(packet_num == 0) { xid = random_xid(); timeout = time(0) + 4; } else if(packet_num == 1) timeout = time(0) + 8; else if(packet_num == 2) timeout = time(0) + 16; else if(packet_num == 3) timeout = time(0) + 32; //} //send_discover(xid, requested_ip); /* broadcast */ packet_num++; } else { if (client_config.abort_if_no_lease) { LOG(LOG_INFO, "No lease, failing."); exit_client(1); } /* wait to try again */ packet_num = 4; //dis_seq = 1; timeout = time(0) + 64; } /* send discover packet */ //printf("DHCP Discover state: %d, time: %d\n", packet_num, timeout); send_discover(xid, requested_ip); /* broadcast */ break; #endif case RENEW_REQUESTED: case REQUESTING: #if 0 if (packet_num < 3) { /* send request packet */ if (state == RENEW_REQUESTED) send_renew(xid, server_addr, requested_ip); /* unicast */ else send_selecting(xid, server_addr, requested_ip); /* broadcast */ timeout = time(0) + ((packet_num == 2) ? 10 : 2); packet_num++; } else { /* timed out, go back to init state */ state = INIT_SELECTING; timeout = time(0); packet_num = 0; listen_mode = LISTEN_RAW; } break; #else if(FirstPass == 1) { if(packet_num < 1) { /* send request packet */ if (state == RENEW_REQUESTED) { printf("RENEW_REQUESTED\n"); send_renew(xid, server_addr, requested_ip); /* unicast */ } else { printf("REQUESTING : %d\n", retval); send_selecting(xid, server_addr, requested_ip); /* broadcast */ } timeout = time(0) + 64; packet_num++; } else { state = INIT_SELECTING; timeout = time(0); packet_num = 4; listen_mode = LISTEN_RAW; } break; } if (packet_num < 6) { if(packet_num == 0) timeout = time(0) + 4; else if(packet_num == 1) timeout = time(0) + 8; else if(packet_num == 2) timeout = time(0) + 16; else if(packet_num == 3) timeout = time(0) + 32; else timeout = time(0) + 64; /* send request packet */ if (state == RENEW_REQUESTED) { //printf("send renew 1\n"); send_renew(xid, server_addr, requested_ip); /* unicast */ } else send_selecting(xid, server_addr, requested_ip); /* broadcast */ packet_num++; } else { FirstPass = 1; /* timed out, go back to init state */ state = INIT_SELECTING; timeout = time(0); packet_num = 4; listen_mode = LISTEN_RAW; } printf("RENEW_REQUESTED, REQUESTING ==> FirstPass: %d\n", FirstPass); break; #endif case BOUND: /* Lease is starting to run out, time to enter renewing state */ state = RENEWING; listen_mode = LISTEN_KERNEL; DEBUG(LOG_INFO, "Entering renew state"); //printf("BOUND\n"); /* fall right through */ case RENEWING: /* Either set a new T1, or enter REBINDING state */ if ((t2 - t1) <= (lease / 14400 + 1)) { /* timed out, enter rebinding state */ state = REBINDING; timeout = time(0) + (t2 - t1); DEBUG(LOG_INFO, "Entering rebinding state"); //printf("RENEWING\n"); } else { //printf("send renew 2 , t1:%ld t2:%ld start:%ld\n", t1, t2, start); /* send a request packet */ send_renew(xid, server_addr, requested_ip); /* unicast */ #if 0 t1 = (t2 - t1) / 2 + t1; timeout = t1 + start; #else t1 = t2; timeout = start + 4; packet_num = 0; #endif //printf("timeout:%ld, t1:%ld\n", timeout, t1); } break; case REBINDING: /* Either set a new T2, or enter INIT state */ if ((lease - t2) <= (lease / 14400 + 1)) { /* timed out, enter init state */ state = INIT_SELECTING; LOG(LOG_INFO, "Lease lost, entering init state"); run_script(NULL, "deconfig"); timeout = time(0); packet_num = 0; listen_mode = LISTEN_RAW; } else { /* send a request packet */ send_renew(xid, 0, requested_ip); /* broadcast */ #if 0 t2 = (lease - t2) / 2 + t2; timeout = t2 + start; #else if(packet_num < 5) { if(packet_num == 0) timeout = time(0) + 4; else if(packet_num == 1) timeout = time(0) + 8; else if(packet_num == 2) timeout = time(0) + 16; else if(packet_num == 3) timeout = time(0) + 32; else if(packet_num == 4) timeout = time(0) + 64; packet_num++ ; } else { /* timed out, go back to init state */ state = INIT_SELECTING; timeout = time(0) + 0; packet_num = 0; listen_mode = LISTEN_RAW; } #endif } printf("REBINDING\n"); break; case RELEASED: /* yah, I know, *you* say it would never happen */ timeout = 0xffffffff; //printf("RELEASED\n"); break; } } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) { /* a packet is ready, read it */ if (listen_mode == LISTEN_KERNEL) { if (get_packet(&packet, fd) < 0) continue; } else { if (get_raw_packet(&packet, fd) < 0) continue; } if (packet.xid != xid) { DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)", (unsigned long) packet.xid, xid); continue; } if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); continue; } switch (state) { case INIT_SELECTING: /* Must be a DHCPOFFER to one of our xid's */ if (*message == DHCPOFFER) { if ((temp = get_option(&packet, DHCP_SERVER_ID))) { memcpy(&server_addr, temp, 4); xid = packet.xid; requested_ip = packet.yiaddr; /* enter requesting state */ state = REQUESTING; timeout = time(0); packet_num = 0; } else { DEBUG(LOG_ERR, "No server ID in message"); } } //dis_seq = 0; //printf(" XXX INIT_SELECTING\n"); break; case RENEW_REQUESTED: case REQUESTING: case RENEWING: case REBINDING: if (*message == DHCPACK) { if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease"); lease = 60*60; } else { memcpy(&lease, temp, 4); lease = ntohl(lease); } FirstPass = 0; packet_num = 0; /* enter bound state */ t1 = lease / 2; /* little fixed point for n * .875 */ t2 = (lease * 0x7) >> 3; temp_addr.s_addr = packet.yiaddr; LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", inet_ntoa(temp_addr), lease); start = time(0); timeout = t1 + start; requested_ip = packet.yiaddr; run_script(&packet, ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); state = BOUND; listen_mode = LISTEN_NONE; // brcm setStatus(1); //printf("Receive Ack: timeout: %d Lease time: %ld, FirstPass: %d\n", timeout, lease, FirstPass); //background(); } else if (*message == DHCPNAK) { /* return to init state */ LOG(LOG_INFO, "Received DHCP NAK"); if (state != REQUESTING) run_script(NULL, "deconfig"); state = INIT_SELECTING; timeout = time(0); requested_ip = 0; packet_num = 0; listen_mode = LISTEN_RAW; // brcm setStatus(0); } //printf("XXX RENEW_REQUESTED, REQUESTING, RENEWING, REBINDING\n"); break; case BOUND: case RELEASED: //printf("XXX BOUND, RELEASED\n"); /* ignore all packets */ break; } } else if (retval == -1 && errno == EINTR) {
int main (int argc, char **argv) { int h, i, fd1 = -1; char buf1[BUF_SIZE], buf2[BUF_SIZE]; // buf1 what port reads from extern prog = tx // buf2 what port sends to extern prog = rx int buf1_avail = 0, buf1_written = 0; int buf2_avail = 0, buf2_written = 0; // vars of my test prog char zeichen; char quitsignal = '#'; if (argc != 2) { fprintf (stderr, "\n\t* * * dl4mge 's PORTECHO. Little TCP test program * * *\n" "\t* * * for tests with hf's mailbox function. * * *\n" "\n" "\tUsage: portecho <port>, e.g. 'portecho 3333'.\n" "\tQuit me with '#'. \n\n"); // <forward-to-port> <forward-to-ip-address>\n"); exit (1); } fprintf (stdout, "\n\t* * * dl4mge 's PORTECHO. Little TCP test program * * *\n" "\t* * * for tests with hf's mailbox function. * * *\n" "\n" "\tTest me on another console by 'telnet localhost <port>'.\n" "\tQuit me with '#'. \n\n"); signal (SIGPIPE, SIG_IGN); h = listen_socket (atoi (argv[1])); if (h < 0) { fprintf (stderr, "error on opening port\n"); exit (1); } for (;;) { for (;;) { int r, n = 0; fd_set rd, wr, er; FD_ZERO (&rd); FD_ZERO (&wr); FD_ZERO (&er); FD_SET (h, &rd); n = max (n, h); if (fd1 > 0 && buf1_avail < BUF_SIZE) { fprintf (stderr, "testport ready for read\n"); FD_SET (fd1, &rd); n = max (n, fd1); } if (fd1 > 0 && buf2_avail - buf2_written > 0) { fprintf (stderr, "testport ready for write\n"); FD_SET (fd1, &wr); n = max (n, fd1); } if (fd1 > 0) { fprintf (stderr, "testport ready for err\n"); FD_SET (fd1, &er); n = max (n, fd1); } r = select (n + 1, &rd, &wr, &er, NULL); if (r == -1 && errno == EINTR) continue; if (r < 0) { perror ("select()"); exit (1); } if (FD_ISSET (h, &rd)) { unsigned int l; struct sockaddr_in client_address; fprintf (stderr, "something tries to access port.\n"); memset (&client_address, 0, l =sizeof (client_address)); r = accept (h, (struct sockaddr *) &client_address, &l); fprintf (stderr, "I will try to accept peer port\n"); if (r < 0) { perror ("accept() peer port"); } else { fprintf (stderr, "I accepted peer port\n"); fprintf (stderr, "r = %d\n",r); SHUT_FD1; buf1_avail = buf1_written = 0; buf2_avail = buf2_written = 0; fd1 = r; sprintf(buf2, "%s", greeting); buf2_avail = strlen(greeting); } } // /* NB: read oob data before normal reads if (fd1 > 0) if (FD_ISSET (fd1, &er)) { char c; errno = 0; r = recv (fd1, &c, 1, MSG_OOB); if (r < 1) { SHUT_FD1; } else fprintf (stderr, "error: %s, errno %d\n", &c, errno); } // READ if (fd1 > 0) { if (FD_ISSET (fd1, &rd)) { fprintf (stderr, "try read\n"); r = read (fd1, buf1 + buf1_avail, BUF_SIZE - buf1_avail); if (r < 1) { SHUT_FD1; } else { buf1_avail += r; fprintf (stderr, "read %d chars\n", r); fprintf (stderr, "buf1: %s\n", buf1); } // PROCESS for (i = 0; i < buf1_avail && i < (BUF_SIZE - buf2_avail); i++) { zeichen = buf1[buf1_written++]; if (zeichen != quitsignal) { buf2[buf2_avail++] = toupper(zeichen); } if (zeichen == quitsignal) { fprintf (stderr, "read: Signal to quit: %c !\n", zeichen); quit = 1; sprintf(buf2, "%s", byebye); buf2_avail = strlen(byebye); //exit(0); } } fprintf (stderr, "buf2: %s\n", buf2); } } // WRITE if (fd1 > 0) { if (FD_ISSET (fd1, &wr)) { fprintf (stderr, "write\n"); r = write (fd1, buf2 + buf2_written, buf2_avail - buf2_written); if (r < 1) { SHUT_FD1; } else { buf2_written += r; } } } // /* check if write data has caught read data if (buf1_written == buf1_avail) { buf1_written = buf1_avail = 0; memset(buf1, 0, sizeof(buf1)); } if (buf2_written == buf2_avail) { buf2_written = buf2_avail = 0; memset(buf2, 0, sizeof(buf2)); if (quit) { SHUT_FD1 quit = 0; break; } } } } return 0; }
int main(int argc, char *argv[]) #endif { uint8_t *temp, *message; unsigned long t1 = 0, t2 = 0, xid = 0; unsigned long start = 0, lease; fd_set rfds; int retval; struct timeval tv; int c, len; struct dhcpMessage packet; struct in_addr temp_addr; long now; int max_fd; int sig; int no_clientid = 0; int fail_times = 0; /* how many times that we fail to find a dhcp server */ int server_unicast = 0; static const struct option arg_options[] = { {"clientid", required_argument, 0, 'c'}, {"clientid-none", no_argument, 0, 'C'}, {"foreground", no_argument, 0, 'f'}, {"background", no_argument, 0, 'b'}, {"hostname", required_argument, 0, 'H'}, {"hostname", required_argument, 0, 'h'}, {"interface", required_argument, 0, 'i'}, {"now", no_argument, 0, 'n'}, {"pidfile", required_argument, 0, 'p'}, {"quit", no_argument, 0, 'q'}, {"request", required_argument, 0, 'r'}, {"script", required_argument, 0, 's'}, {"unicast", no_argument, 0, 'u'}, /* unicast flag */ {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; /* get options */ while (1) { int option_index = 0; c = getopt_long(argc, argv, "c:CfbH:h:i:np:qr:s:uv", arg_options, &option_index); if (c == -1) break; switch (c) { case 'c': if (no_clientid) show_usage(); len = strlen(optarg) > 255 ? 255 : strlen(optarg); if (client_config.clientid) free(client_config.clientid); client_config.clientid = xmalloc(len + 2); client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; client_config.clientid[OPT_LEN] = len; client_config.clientid[OPT_DATA] = '\0'; strncpy(client_config.clientid + OPT_DATA, optarg, len); break; case 'C': if (client_config.clientid) show_usage(); no_clientid = 1; break; case 'f': client_config.foreground = 1; break; case 'b': client_config.background_if_no_lease = 1; break; case 'h': case 'H': len = strlen(optarg) > 255 ? 255 : strlen(optarg); if (client_config.hostname) free(client_config.hostname); client_config.hostname = xmalloc(len + 2); client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; client_config.hostname[OPT_LEN] = len; strncpy(client_config.hostname + 2, optarg, len); break; case 'i': client_config.interface = optarg; break; case 'n': client_config.abort_if_no_lease = 1; break; case 'p': client_config.pidfile = optarg; break; case 'q': client_config.quit_after_lease = 1; break; case 'r': requested_ip = inet_addr(optarg); break; case 's': client_config.script = optarg; break; case 'u': server_unicast = 1; break; case 'v': printf("udhcpcd, version %s\n\n", VERSION); return 0; break; default: show_usage(); } } /* Start the log, sanitize fd's, and write a pid file */ start_log_and_pid("udhcpc", client_config.pidfile); if (read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.arp) < 0) return 1; /* if not set, and not suppressed, setup the default client ID */ if (!client_config.clientid && !no_clientid) { client_config.clientid = xmalloc(6 + 3); client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; client_config.clientid[OPT_LEN] = 7; client_config.clientid[OPT_DATA] = 1; memcpy(client_config.clientid + 3, client_config.arp, 6); } /* changed by lsz 070621 */ client_background(); /* setup the signal pipe */ udhcp_sp_setup(); //if (dhcpc_shm_init() != 0) // return -1; #include "msgq.h" dhcp_ipc_fork(DHCPC); state = INIT_SELECTING; run_script(NULL, "deconfig"); change_mode(LISTEN_RAW); for (;;) { tv.tv_sec = timeout - uptime(); tv.tv_usec = 0; if (listen_mode != LISTEN_NONE && fd < 0) { if (listen_mode == LISTEN_KERNEL) fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); else fd = raw_socket(client_config.ifindex); if (fd < 0) { LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m"); return 0; } } /* * select don't return when timeout value is larger than 1.5 hours * we just wait multiple times * added by tiger 090819, should fix later */ struct timeval tp_timeout; #define TP_TIMEOUT_MAX (30*60) if (tv.tv_sec > 0) { do { max_fd = udhcp_sp_fd_set(&rfds, fd); tp_timeout.tv_sec = (tv.tv_sec > TP_TIMEOUT_MAX) ? TP_TIMEOUT_MAX : tv.tv_sec; tv.tv_sec -= tp_timeout.tv_sec; tp_timeout.tv_usec = 0; retval = select(max_fd + 1, &rfds, NULL, NULL, &tp_timeout); } while (tv.tv_sec > 0 && retval == 0); } else { retval = 0; /* If we already timed out, fall through */ } now = uptime(); if (retval == 0) { /* timeout dropped to zero */ switch (state) { case INIT_SELECTING: #define DISCOVER_RETRY_TIMES 5 #define DISCOVER_INVERT_TIMES 3 if (packet_num < DISCOVER_RETRY_TIMES) { if (packet_num == 0) { xid = random_xid(); /* use user config dhcp flags when first discover, added by tiger 20090821 */ if (server_unicast) { set_runtime_dhcp_flags(DHCP_FLAGS_UNICAST); } else { set_runtime_dhcp_flags(DHCP_FLAGS_BROADCAST); } } /* change runtime dhcp flags when exceed DISCOVER_INVERT_TIMES added by tiger 20090819 apply 11G and XP's option */ if (DISCOVER_INVERT_TIMES == packet_num) { invert_runtime_dhcp_flags(); } /* send discover packet */ //send_discover(xid, requested_ip, server_unicast); /* broadcast */ /* modified by tiger 20090304, reply mode's setting way changed */ send_discover(xid, requested_ip); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Send DISCOVER with request ip %X and unicast flag %d", requested_ip, get_runtime_dhcp_flags()); timeout = now + ((packet_num == 2) ? 4 : 2); packet_num++; } else { run_script(NULL, "leasefail"); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC DHCP Service unavailable, recv no OFFER"); if (client_config.background_if_no_lease) { LOG(LOG_INFO, "No lease, forking to background."); client_background(); } else if (client_config.abort_if_no_lease) { LOG(LOG_INFO, "No lease, failing."); return 1; } /* wait to try again */ packet_num = 0; timeout = now + 10 + (fail_times ++) * 30; /* 60->6000, we dont need to try again -- lsz, 080722 */ /* 6000->30*fail_times -- lsz, 081008 */ } break; case RENEW_REQUESTED: case REQUESTING: if (packet_num < 3) { /* send request packet */ if (state == RENEW_REQUESTED) { send_renew(xid, server_addr, requested_ip); /* unicast */ } else { send_selecting(xid, server_addr, requested_ip); /* broadcast */ } msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Send REQUEST to server %x with request ip %x", server_addr, requested_ip); timeout = now + ((packet_num == 2) ? 10 : 2); packet_num++; } else { /* timed out, go back to init state */ if (state == RENEW_REQUESTED) run_script(NULL, "deconfig"); state = INIT_SELECTING; timeout = now; packet_num = 0; change_mode(LISTEN_RAW); } break; case BOUND: /* Lease is starting to run out, time to enter renewing state */ state = RENEWING; change_mode(LISTEN_KERNEL); DEBUG(LOG_INFO, "Entering renew state"); /* fall right through */ case RENEWING: /* Either set a new T1, or enter REBINDING state */ if ((t2 - t1) <= (lease / 14400 + 1)) { /* timed out, enter rebinding state */ state = REBINDING; timeout = now + (t2 - t1); DEBUG(LOG_INFO, "Entering rebinding state"); } else { /* send a request packet */ send_renew(xid, server_addr, requested_ip); /* unicast */ msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Send REQUEST to server %x with request ip %x", server_addr, requested_ip); t1 = (t2 - t1) / 2 + t1; timeout = t1 + start; } break; case REBINDING: /* Either set a new T2, or enter INIT state */ if ((lease - t2) <= (lease / 14400 + 1)) { /* timed out, enter init state */ state = INIT_SELECTING; LOG(LOG_INFO, "Lease lost, entering init state"); run_script(NULL, "deconfig"); timeout = now; packet_num = 0; change_mode(LISTEN_RAW); } else { /* send a request packet */ send_renew(xid, 0, requested_ip); /* broadcast */ msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Broadcast REQUEST with request ip %x", requested_ip); t2 = (lease - t2) / 2 + t2; timeout = t2 + start; } break; case RELEASED: /* yah, I know, *you* say it would never happen */ timeout = 0x7fffffff; break; } } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) { /* a packet is ready, read it */ if (listen_mode == LISTEN_KERNEL) len = get_packet(&packet, fd); else len = get_raw_packet(&packet, fd); if (len == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %m, reopening socket"); change_mode(listen_mode); /* just close and reopen */ } if (len < 0) continue; if (packet.xid != xid) { DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)", (unsigned long) packet.xid, xid); continue; } /* Ignore packets that aren't for us */ if (memcmp(packet.chaddr, client_config.arp, 6)) { DEBUG(LOG_INFO, "packet does not have our chaddr -- ignoring"); continue; } if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); continue; } switch (state) { case INIT_SELECTING: /* Must be a DHCPOFFER to one of our xid's */ if (*message == DHCPOFFER) { if ((temp = get_option(&packet, DHCP_SERVER_ID))) { memcpy(&server_addr, temp, 4); xid = packet.xid; requested_ip = packet.yiaddr; msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Recv OFFER from server %x with ip %x", server_addr, requested_ip); /* enter requesting state */ state = REQUESTING; timeout = now; packet_num = 0; } else { DEBUG(LOG_ERR, "No server ID in message"); } } break; case RENEW_REQUESTED: case REQUESTING: case RENEWING: case REBINDING: if (*message == DHCPACK) { if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease"); lease = 60 * 60; } else { memcpy(&lease, temp, 4); lease = ntohl(lease); } /* RFC 2131 3.1 paragraph 5: * "The client receives the DHCPACK message with configuration * parameters. The client SHOULD perform a final check on the * parameters (e.g., ARP for allocated network address), and notes * the duration of the lease specified in the DHCPACK message. At this * point, the client is configured. If the client detects that the * address is already in use (e.g., through the use of ARP), * the client MUST send a DHCPDECLINE message to the server and restarts * the configuration process..." * added by tiger 20090827 */ if (!arpping(packet.yiaddr, (uint32_t) 0, packet.yiaddr, client_config.arp, client_config.interface) ) { msglogd (LOG_INFO, LOGTYPE_DHCP, "DHCPC: offered address is in use " "(got ARP reply), Send decline"); send_decline(xid, server_addr, packet.yiaddr); if (state != REQUESTING) run_script(NULL, "deconfig"); change_mode(LISTEN_RAW); state = INIT_SELECTING; requested_ip = 0; timeout = now + 12; packet_num = 0; continue; /* back to main loop */ } /* enter bound state */ t1 = lease / 2; /* little fixed point for n * .875 */ t2 = (lease * 0x7) >> 3; temp_addr.s_addr = packet.yiaddr; LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", inet_ntoa(temp_addr), lease); start = now; timeout = t1 + start; requested_ip = packet.yiaddr; if ((temp = get_option(&packet, DHCP_SERVER_ID))) memcpy(&server_addr, temp, 4); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Recv ACK from server %x with ip %x lease time %ld", server_addr, requested_ip, lease); run_script(&packet, ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); fail_times = 0; /* clear the retry counter */ state = BOUND; change_mode(LISTEN_NONE); if (client_config.quit_after_lease) return 0; if (!client_config.foreground) client_background(); } else if (*message == DHCPNAK) { /* return to init state */ LOG(LOG_INFO, "Received DHCP NAK"); if ((temp = get_option(&packet, DHCP_SERVER_ID))) memcpy(&server_addr, temp, 4); msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Recv NAK from server %x with ip %x", server_addr, requested_ip); run_script(&packet, "nak"); if (state != REQUESTING) run_script(NULL, "deconfig"); state = INIT_SELECTING; timeout = now + 3; /* change by lsz 080905, without this 3 seconds, * the udhcpc will keep on trying and the release * msg cant be recved by udhcpc, even if we are * wan static ip now, the udhcpc is still sending * discover pkts. */ requested_ip = 0; packet_num = 0; change_mode(LISTEN_RAW); //sleep(3); /* avoid excessive network traffic */ } break; /* case BOUND, RELEASED: - ignore all packets */ } } else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) {
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; }
void *recv_data (connection_data *connection, int timer) { char *ptr = NULL, *data = NULL; data_packet *data_ptr = NULL; handshake_packet *hs_ptr = NULL; fd_set listen_set; int result, client_index; #ifdef _DEBUG_ printf("Listen socket in recv-data\n"); #endif ptr = listen_socket(connection, timer, 0); #ifdef _DEBUG_ if (ptr != NULL) printf("ptr in recv_data is: %s\n and ptr[5] is: %c\n", ptr, ptr[5]); #endif if (ptr != NULL) { switch(atoi(&ptr[5])) { case HANDSHAKE: hs_ptr = string_to_packet(ptr, HANDSHAKE); if (!is_packet(hs_ptr, HANDSHAKE) && (connection->client_id == 7 || connection->client_id == hs_ptr->client_id)) { #ifdef _DEBUG_ printf("It is a handshake packet!\n"); #endif if (hs_ptr->flags != RST) { free(hs_ptr); return NULL; } else { connection_termination(connection, SERVER); free(hs_ptr); return "Terminated"; } } else { #ifdef _DEBUG_ printf("Is not a packet :(\n"); #endif return NULL; } break; case DATA: data_ptr = string_to_packet(ptr, DATA); if (!is_packet(data_ptr, DATA)) { #ifdef _DEBUG_ printf("Data packet received, containing data: %s\n", (char *)data_ptr->data); #endif client_index = data_ptr->client_id-1; #ifdef _DEBUG_ printf("Client_index: %d\n", client_index); printf("Last_seen_pkt[%d] = %d data_ptr->seq_nr = %d\n", client_index, connection->last_seen_pkt[client_index], data_ptr->seq_nr); #endif if (data_ptr->seq_nr > connection->last_seen_pkt[client_index]) { #ifdef _DEBUG_ printf("Data packet is newer than last seen, using...\n"); #endif connection->last_seen_pkt[client_index] = data_ptr->seq_nr; data = strdup(data_ptr->data); free(data_ptr); #ifdef _DEBUG_ printf("Last_seen_pkt[%d] = %d\n", client_index, connection->last_seen_pkt[client_index]); #endif return data; } else { #ifdef _DEBUG_ printf("Packet out of order, dumping...\n"); #endif return NULL; } } else { return NULL; } default: return NULL; } } else { return NULL; } }
int connect_session(connection_data *connection, char *server_ip, uint16_t server_port, uint16_t client_port) { handshake_packet syn_packet, *received_packet = NULL; struct sockaddr_in server, client; socklen_t client_len; int i = 0, return_value = 0; char *ptr = NULL; char *client_ip = malloc(sizeof(char) * 16); uint32_t sock_fd = 0; srand(time(NULL)); net_init(); #ifdef _DEBUG_ printf("Before creating socket.\n"); #endif if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket() failed"); return -1; } #ifdef _DEBUG_ printf("After creating socket.\n"); printf("Creating sockaddr_in to find out client ip\n"); #endif memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(server_ip); server.sin_port = htons(server_port); #ifdef _DEBUG_ printf("Using a connected UDP socket to find out client ip\n"); #endif if (connect(sock_fd, (struct sockaddr *)&server, sizeof(server)) < 0) { perror("connect() failed (in trying to find out client ip)"); return -1; } client_len = sizeof(client); #ifdef _DEBUG_ printf("Using getsockname() to get local IP the socket bound to\n"); #endif if (getsockname(sock_fd, (struct sockaddr *)&client, &client_len) < 0) { perror("getsockname() failed when trying to find out client ip"); return -1; } #ifdef _DEBUG_ printf("Fetching the IP address from client sockaddr struct\n"); #endif if (inet_ntop(AF_INET, &client.sin_addr, client_ip, 16) < 0) { perror("inet_ntop() failed to get client ip"); return -1; } CLOSE(sock_fd); #ifdef _DEBUG_ printf("Client ip in buffer: %s\n", client_ip); printf("Before creating socket.\n"); #endif if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket() failed"); return -1; } #ifdef _DEBUG_ printf("After creating socket.\n"); printf("Preparing SYN packet.\n"); #endif syn_packet.proto_id = "herp"; syn_packet.packet_type = HANDSHAKE; syn_packet.client_ip = client_ip; syn_packet.client_port = client_port; syn_packet.client_id = rand(); syn_packet.flags = SYN; syn_packet.trailer = "derp"; #ifdef _DEBUG_ printf("Converting to string.\n"); #endif ptr = packet_to_string(&syn_packet, HANDSHAKE); #ifdef _DEBUG_ printf("Setting up listening socket.\n"); #endif connection = create_connection_data(client_ip, client_port, syn_packet.client_id, sock_fd, connection); #ifdef _DEBUG_ printf("Binding socket.\n"); #endif if (bind(connection->sock_fd, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("Bind() failed"); CLOSE(connection->sock_fd); return -1; } #ifdef _DEBUG_ printf("Creating connection_data.\n"); #endif connection = create_connection_data(server_ip, server_port, syn_packet.client_id, connection->sock_fd, connection); connection->client_ip = client_ip; connection->client_port = client_port; for(i = 0; i < 3; i++) { #ifdef _DEBUG_ printf("Try %d\n", i+1); printf("Struct data: %d %d %d socket: %d client_id: %d\n", connection->destination->sin_family, connection->destination->sin_port, connection->destination->sin_addr.s_addr, connection->sock_fd, connection->client_id); #endif if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("sendto() failed"); CLOSE(connection->sock_fd); return -1; } #ifdef _DEBUG_ printf("Entering listening mode.\n"); #endif ptr = listen_socket(connection, 5, 0); #ifdef _DEBUG_ if (ptr != NULL) printf("Received string: %s\n", ptr); #endif if (ptr != NULL) { if (atoi(&ptr[5]) == HANDSHAKE) { #ifdef _DEBUG_ printf("It is a handshake packet outside recv_data!\n"); #endif received_packet = (handshake_packet *)string_to_packet(ptr, HANDSHAKE); #ifdef _DEBUG_ printf("ptr size %d\n", strlen(ptr)); #endif if (!is_packet(received_packet, HANDSHAKE) && !strncmp(connection->client_ip, received_packet->client_ip, strlen(connection->client_ip)) && (received_packet->flags == ACK)) { #ifdef _DEBUG_ printf("ACK packet received: %p.\n", connection); #endif connection->client_id = received_packet->client_id; free(client_ip); return 0; } } else { #ifdef _DEBUG_ printf("Is not a packet :(\n"); #endif break; } } } fprintf(stderr, "No server responded with a ACK, stopping connection attempts...\n"); free(client_ip); return 1; }
int end_session(connection_data *connection) { handshake_packet rst_packet, *received_packet = NULL; char *ptr = NULL; int i; rst_packet.proto_id = "herp"; rst_packet.packet_type = HANDSHAKE; rst_packet.client_ip = connection->client_ip; rst_packet.client_port = connection->client_port; rst_packet.client_id = connection->client_id; rst_packet.flags = RST; rst_packet.trailer = "derp"; ptr = packet_to_string(&rst_packet, HANDSHAKE); if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("sendto() failed"); CLOSE(connection->sock_fd); return -1; } for (i = 0; i < 2; i++) { #ifdef _DEBUG_ printf("Listening for ACK packet from termination.\n"); #endif ptr = listen_socket(connection, 3, 0); #ifdef _DEBUG_ if (ptr != NULL) { printf("ptr size %d\n", strlen(ptr)); printf("packet type: %d ptr: %s\n", atoi(&ptr[5]), ptr); } #endif if (ptr != NULL) { if (atoi(&ptr[5]) == HANDSHAKE) { #ifdef _DEBUG_ printf("Converting from string to packet.\n"); #endif received_packet = (handshake_packet *)string_to_packet (ptr, HANDSHAKE); #ifdef _DEBUG_ printf("It is a handshake packet outside recv_data()!\n"); #endif if (!is_packet(received_packet, HANDSHAKE) && (received_packet->flags == ACK)) { #ifdef _DEBUG_ printf("ACK Packet received.\n"); #endif connection_termination(connection, CLIENT); break; } } } } free(received_packet); return 0; }
int accept_session (connection_data *connection, uint16_t port, int client_id) { handshake_packet ack_packet, *received_packet = NULL; static int first_time = 1; static uint16_t sock_fd; char *ptr = NULL; if (first_time) { #ifdef _DEBUG_ printf("Inside a first_time only\n"); #endif net_init(); #ifdef _DEBUG_ printf("Before creating socket.\n"); #endif if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { perror("socket() failed"); return -1; } #ifdef _DEBUG_ printf("After creating socket.\n"); #endif } connection = create_connection_data("0.0.0.0", port, 0, sock_fd, connection); if (first_time) { #ifdef _DEBUG_ printf("Setting up listening socket.\n"); printf("Binding socket.\n"); #endif if (bind(sock_fd, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("Bind() failed"); CLOSE(sock_fd); return -1; } first_time = 0; } while(1) { #ifdef _DEBUG_ printf("Listening for SYN packet.\n"); printf("connection->sock_fd: %d\n", connection->sock_fd); #endif ptr = listen_socket(connection, 60, 0); #ifdef _DEBUG_ printf("Received string: %s\n", ptr); #endif if (ptr != NULL) { if (atoi(&ptr[5]) == HANDSHAKE) { #ifdef _DEBUG_ printf("Converting from string to packet.\n"); #endif received_packet = (handshake_packet *)string_to_packet(ptr, HANDSHAKE); #ifdef _DEBUG_ printf("ptr size %d\n", strlen(ptr)); printf("It is a handshake packet outside recv_data!\n"); printf("Content: %s %u %s %u %u %s\n", received_packet->proto_id, received_packet->packet_type, received_packet->client_ip, received_packet->client_port, received_packet->flags, received_packet->trailer); #endif if (!is_packet(received_packet, HANDSHAKE) && received_packet->flags == SYN) { #ifdef _DEBUG_ printf("SYN Packet received.\n"); #endif break; } else if (!is_packet(received_packet, HANDSHAKE) && received_packet->flags == RST) { connection_termination(connection, SERVER); return 1; } } } } #ifdef _DEBUG_ printf("Preparing ACK packet.\n"); #endif ack_packet.proto_id = "herp"; ack_packet.packet_type = HANDSHAKE; ack_packet.client_ip = received_packet->client_ip; ack_packet.client_port = received_packet->client_port; ack_packet.client_id = client_id; ack_packet.flags = ACK; ack_packet.trailer = "derp"; #ifdef _DEBUG_ printf("Creating connection_data struct.\n"); #endif connection = create_connection_data(received_packet->client_ip, received_packet->client_port, client_id, connection->sock_fd, connection); #ifdef _DEBUG_ printf("Converting packet_to_string.\n"); #endif ptr = packet_to_string(&ack_packet, HANDSHAKE); #ifdef _DEBUG_ printf("Sending ACK packet.\n"); #endif if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) { perror("sendto() failed"); CLOSE(connection->sock_fd); return -1; } #ifdef _DEBUG_ printf("pointer address %p\n", connection); #endif free(received_packet); free(ptr); return 0; }