Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/udhcp
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- Location:
- branches/stable/mindi-busybox/networking/udhcp
- Files:
-
- 16 deleted
- 21 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/udhcp/Config.in
r821 r1770 4 4 # 5 5 6 menu "udhcp Server/Client" 7 8 config CONFIG_APP_UDHCPD 6 config APP_UDHCPD 9 7 bool "udhcp Server (udhcpd)" 10 8 default n … … 15 13 See http://udhcp.busybox.net for further details. 16 14 17 config CONFIG_APP_UDHCPC 15 config APP_DHCPRELAY 16 bool "dhcprelay" 17 default n 18 depends on APP_UDHCPD 19 help 20 dhcprelay listens for dhcp requests on one or more interfaces 21 and forwards these requests to a different interface or dhcp 22 server. 23 24 config APP_DUMPLEASES 25 bool "Lease display utility (dumpleases)" 26 default n 27 depends on APP_UDHCPD 28 help 29 dumpleases displays the leases written out by the udhcpd server. 30 Lease times are stored in the file by time remaining in lease, or 31 by the absolute time that it expires in seconds from epoch. 32 33 See http://udhcp.busybox.net for further details. 34 35 config FEATURE_UDHCPD_WRITE_LEASES_EARLY 36 bool "Rewrite the lease file at every new acknowledge" 37 default n 38 depends on APP_UDHCPD 39 help 40 If selected, udhcpd will write a new file with leases every 41 time a new lease has been accepted, thus eleminating the need 42 to send SIGUSR1 for the initial writing, or updating. Any timed 43 rewriting remains undisturbed 44 45 config APP_UDHCPC 18 46 bool "udhcp Client (udhcpc)" 19 47 default n … … 27 55 See http://udhcp.busybox.net for further details. 28 56 29 config CONFIG_APP_DUMPLEASES30 bool " Lease display utility (dumpleases)"57 config FEATURE_UDHCP_DEBUG 58 bool "Compile udhcp with noisy debugging messages" 31 59 default n 32 depends on CONFIG_APP_UDHCPD 33 help 34 dumpleases displays the leases written out by the udhcpd server. 35 Lease times are stored in the file by time remaining in lease, or 36 by the absolute time that it expires in seconds from epoch. 37 38 See http://udhcp.busybox.net for further details. 39 40 config CONFIG_FEATURE_UDHCP_SYSLOG 41 bool " Log udhcp messages to syslog (instead of stdout)" 42 default n 43 depends on CONFIG_APP_UDHCPD || CONFIG_APP_UDHCPC 44 help 45 If selected, udhcpd will log all its messages to syslog, otherwise, 46 it will attempt to log them to stdout. 47 48 See http://udhcp.busybox.net for further details. 49 50 config CONFIG_FEATURE_UDHCP_DEBUG 51 bool " Compile udhcp with noisy debugging messages" 52 default n 53 depends on CONFIG_APP_UDHCPD || CONFIG_APP_UDHCPC 60 depends on APP_UDHCPD || APP_UDHCPC 54 61 help 55 62 If selected, udhcpd will output extra debugging output. If using … … 59 66 See http://udhcp.busybox.net for further details. 60 67 61 endmenu 62 68 config FEATURE_RFC3397 69 bool "Support for RFC3397 domain search (experimental)" 70 default n 71 depends on APP_UDHCPD || APP_UDHCPC 72 help 73 If selected, both client and server will support passing of domain 74 search lists via option 119, specified in RFC3397. -
branches/stable/mindi-busybox/networking/udhcp/arpping.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * arpping.c … … 6 7 */ 7 8 8 #include <time.h>9 #include <sys/socket.h>10 9 #include <netinet/if_ether.h> 11 10 #include <net/if_arp.h> 12 #include <netinet/in.h>13 #include <string.h>14 #include <unistd.h>15 #include <errno.h>16 11 12 #include "common.h" 17 13 #include "dhcpd.h" 18 #include "arpping.h"19 #include "common.h"20 21 /* args: yiaddr - what IP to ping22 * ip - our ip23 * mac - our arp address24 * interface - interface to use25 * retn: 1 addr free26 * 0 addr used27 * -1 error28 */29 30 /* FIXME: match response against chaddr */31 int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)32 {33 34 int timeout = 2;35 int optval = 1;36 int s; /* socket */37 int rv = 1; /* return value */38 struct sockaddr addr; /* for interface name */39 struct arpMsg arp;40 fd_set fdset;41 struct timeval tm;42 time_t prevTime;43 14 44 15 45 if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) { 46 #ifdef IN_BUSYBOX 47 LOG(LOG_ERR, bb_msg_can_not_create_raw_socket); 48 #else 49 LOG(LOG_ERR, "Could not open raw socket"); 50 #endif 16 struct arpMsg { 17 /* Ethernet header */ 18 uint8_t h_dest[6]; /* 00 destination ether addr */ 19 uint8_t h_source[6]; /* 06 source ether addr */ 20 uint16_t h_proto; /* 0c packet type ID field */ 21 22 /* ARP packet */ 23 uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */ 24 uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */ 25 uint8_t hlen; /* 12 hardware address length (must be 6) */ 26 uint8_t plen; /* 13 protocol address length (must be 4) */ 27 uint16_t operation; /* 14 ARP opcode */ 28 uint8_t sHaddr[6]; /* 16 sender's hardware address */ 29 uint8_t sInaddr[4]; /* 1c sender's IP address */ 30 uint8_t tHaddr[6]; /* 20 target's hardware address */ 31 uint8_t tInaddr[4]; /* 26 target's IP address */ 32 uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */ 33 } ATTRIBUTE_PACKED; 34 35 36 /* Returns 1 if no reply received */ 37 38 int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface) 39 { 40 int timeout = 2; 41 int s; /* socket */ 42 int rv = 1; /* "no reply received" yet */ 43 struct sockaddr addr; /* for interface name */ 44 struct arpMsg arp; 45 fd_set fdset; 46 struct timeval tm; 47 unsigned prevTime; 48 49 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); 50 if (s == -1) { 51 bb_perror_msg(bb_msg_can_not_create_raw_socket); 51 52 return -1; 52 53 } 53 54 54 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) { 55 LOG(LOG_ERR, "Could not setsocketopt on raw socket"); 56 close(s); 57 return -1; 55 if (setsockopt_broadcast(s) == -1) { 56 bb_perror_msg("cannot setsocketopt on raw socket"); 57 goto ret; 58 58 } 59 59 60 60 /* send arp request */ 61 61 memset(&arp, 0, sizeof(arp)); 62 memcpy(arp.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */ 63 memcpy(arp.h_source, mac, 6); /* MAC SA */ 64 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ 65 arp.htype = htons(ARPHRD_ETHER); /* hardware type */ 66 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ 67 arp.hlen = 6; /* hardware address length */ 68 arp.plen = 4; /* protocol address length */ 69 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ 70 memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */ 71 memcpy(arp.sHaddr, mac, 6); /* source hardware address */ 72 memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */ 62 memset(arp.h_dest, 0xff, 6); /* MAC DA */ 63 memcpy(arp.h_source, from_mac, 6); /* MAC SA */ 64 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ 65 arp.htype = htons(ARPHRD_ETHER); /* hardware type */ 66 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ 67 arp.hlen = 6; /* hardware address length */ 68 arp.plen = 4; /* protocol address length */ 69 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ 70 memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */ 71 memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */ 72 /* tHaddr */ /* target hardware address */ 73 memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */ 73 74 74 75 memset(&addr, 0, sizeof(addr)); 75 s trcpy(addr.sa_data, interface);76 safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data)); 76 77 if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) 77 rv = 0;78 goto ret; 78 79 79 /* wait arp reply, and check it */80 tm.tv_usec = 0;81 prevTime = uptime();82 while (timeout > 0) {80 /* wait for arp reply, and check it */ 81 do { 82 int r; 83 prevTime = monotonic_sec(); 83 84 FD_ZERO(&fdset); 84 85 FD_SET(s, &fdset); 85 86 tm.tv_sec = timeout; 86 if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) { 87 DEBUG(LOG_ERR, "Error on ARPING request: %m"); 88 if (errno != EINTR) rv = 0; 89 } else if (FD_ISSET(s, &fdset)) { 90 if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0; 91 if (arp.operation == htons(ARPOP_REPLY) && 92 memcmp(arp.tHaddr, mac, 6) == 0 && 93 *((uint32_t *) arp.sInaddr) == yiaddr) { 94 DEBUG(LOG_INFO, "Valid arp reply receved for this address"); 87 tm.tv_usec = 0; 88 r = select(s + 1, &fdset, NULL, NULL, &tm); 89 if (r < 0) { 90 bb_perror_msg("error on ARPING request"); 91 if (errno != EINTR) 92 break; 93 } else if (r) { 94 if (recv(s, &arp, sizeof(arp), 0) < 0) 95 break; 96 if (arp.operation == htons(ARPOP_REPLY) 97 && memcmp(arp.tHaddr, from_mac, 6) == 0 98 && *((uint32_t *) arp.sInaddr) == test_ip 99 ) { 95 100 rv = 0; 96 101 break; 97 102 } 98 103 } 99 timeout -= uptime() - prevTime; 100 prevTime = uptime(); 101 } 104 timeout -= monotonic_sec() - prevTime; 105 } while (timeout > 0); 106 107 ret: 102 108 close(s); 103 DEBUG( LOG_INFO, "%salid arp replies for this address", rv ? "No v" : "V");109 DEBUG("%srp reply received for this address", rv ? "No a" : "A"); 104 110 return rv; 105 111 } -
branches/stable/mindi-busybox/networking/udhcp/clientpacket.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* clientpacket.c 2 3 * … … 8 9 */ 9 10 10 #include <string.h>11 #include <sys/socket.h>12 11 #include <features.h> 13 #if ( __GLIBC__ >= 2 && __GLIBC_MINOR>= 1) || defined _NEWLIB_VERSION12 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION 14 13 #include <netpacket/packet.h> 15 14 #include <net/ethernet.h> … … 19 18 #include <linux/if_ether.h> 20 19 #endif 21 #include <stdlib.h> 22 #include <time.h> 23 #include <unistd.h> 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <fcntl.h> 27 28 20 21 #include "common.h" 29 22 #include "dhcpd.h" 30 #include " clientpacket.h"23 #include "dhcpc.h" 31 24 #include "options.h" 32 #include "dhcpc.h"33 #include "common.h"34 25 35 26 36 27 /* Create a random xid */ 37 unsigned long random_xid(void) 38 { 39 static int initialized; 28 uint32_t random_xid(void) 29 { 30 static smallint initialized; 31 40 32 if (!initialized) { 41 int fd; 42 unsigned long seed; 43 44 fd = open("/dev/urandom", 0); 45 if (fd < 0 || read(fd, &seed, sizeof(seed)) < 0) { 46 LOG(LOG_WARNING, "Could not load seed from /dev/urandom: %m"); 47 seed = time(0); 48 } 49 if (fd >= 0) close(fd); 50 srand(seed); 51 initialized++; 33 srand(monotonic_us()); 34 initialized = 1; 52 35 } 53 36 return rand(); … … 61 44 memcpy(packet->chaddr, client_config.arp, 6); 62 45 if (client_config.clientid) 63 add_option_string(packet->options, client_config.clientid); 64 if (client_config.hostname) add_option_string(packet->options, client_config.hostname); 65 if (client_config.fqdn) add_option_string(packet->options, client_config.fqdn); 46 add_option_string(packet->options, client_config.clientid); 47 if (client_config.hostname) 48 add_option_string(packet->options, client_config.hostname); 49 if (client_config.fqdn) 50 add_option_string(packet->options, client_config.fqdn); 66 51 add_option_string(packet->options, client_config.vendorclass); 67 52 } … … 87 72 88 73 /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ 89 int send_discover(u nsigned long xid, unsigned longrequested)74 int send_discover(uint32_t xid, uint32_t requested) 90 75 { 91 76 struct dhcpMessage packet; … … 97 82 98 83 add_requests(&packet); 99 LOG(LOG_DEBUG, "Sending discover..."); 84 bb_info_msg("Sending discover..."); 85 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, 86 SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); 87 } 88 89 90 /* Broadcasts a DHCP request message */ 91 int send_selecting(uint32_t xid, uint32_t server, uint32_t requested) 92 { 93 struct dhcpMessage packet; 94 struct in_addr addr; 95 96 init_packet(&packet, DHCPREQUEST); 97 packet.xid = xid; 98 99 add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); 100 add_simple_option(packet.options, DHCP_SERVER_ID, server); 101 102 add_requests(&packet); 103 addr.s_addr = requested; 104 bb_info_msg("Sending select for %s...", inet_ntoa(addr)); 100 105 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, 101 106 SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); … … 103 108 104 109 105 /* Broadcasts a DHCP request message */106 int send_selecting(unsigned long xid, unsigned long server, unsigned long requested)107 {108 struct dhcpMessage packet;109 struct in_addr addr;110 111 init_packet(&packet, DHCPREQUEST);112 packet.xid = xid;113 114 add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);115 add_simple_option(packet.options, DHCP_SERVER_ID, server);116 117 add_requests(&packet);118 addr.s_addr = requested;119 LOG(LOG_DEBUG, "Sending select for %s...", inet_ntoa(addr));120 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,121 SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);122 }123 124 125 110 /* Unicasts or broadcasts a DHCP renew message */ 126 int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr) 127 { 128 struct dhcpMessage packet; 129 int ret = 0; 111 int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) 112 { 113 struct dhcpMessage packet; 130 114 131 115 init_packet(&packet, DHCPREQUEST); … … 134 118 135 119 add_requests(&packet); 136 LOG(LOG_DEBUG,"Sending renew...");120 bb_info_msg("Sending renew..."); 137 121 if (server) 138 ret = udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); 139 else ret = udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, 122 return udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); 123 124 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, 140 125 SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); 141 return ret;142 126 } 143 127 144 128 145 129 /* Unicasts a DHCP release message */ 146 int send_release(u nsigned long server, unsigned longciaddr)130 int send_release(uint32_t server, uint32_t ciaddr) 147 131 { 148 132 struct dhcpMessage packet; … … 155 139 add_simple_option(packet.options, DHCP_SERVER_ID, server); 156 140 157 LOG(LOG_DEBUG,"Sending release...");141 bb_info_msg("Sending release..."); 158 142 return udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); 159 143 } … … 171 155 bytes = read(fd, &packet, sizeof(struct udp_dhcp_packet)); 172 156 if (bytes < 0) { 173 DEBUG( LOG_INFO, "couldn't read on raw listening socket -- ignoring");157 DEBUG("Cannot read on raw listening socket - ignoring"); 174 158 usleep(500000); /* possible down interface, looping condition */ 175 159 return -1; … … 177 161 178 162 if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) { 179 DEBUG( LOG_INFO, "message too short, ignoring");163 DEBUG("Message too short, ignoring"); 180 164 return -2; 181 165 } 182 166 183 167 if (bytes < ntohs(packet.ip.tot_len)) { 184 DEBUG( LOG_INFO,"Truncated packet");168 DEBUG("Truncated packet"); 185 169 return -2; 186 170 } … … 190 174 191 175 /* Make sure its the right packet for us, and that it passes sanity checks */ 192 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION || 193 packet.ip.ihl != sizeof(packet.ip) >> 2 || packet.udp.dest != htons(CLIENT_PORT) || 194 bytes > (int) sizeof(struct udp_dhcp_packet) || 195 ntohs(packet.udp.len) != (uint16_t) (bytes - sizeof(packet.ip))) { 196 DEBUG(LOG_INFO, "unrelated/bogus packet"); 176 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION 177 || packet.ip.ihl != sizeof(packet.ip) >> 2 178 || packet.udp.dest != htons(CLIENT_PORT) 179 || bytes > (int) sizeof(struct udp_dhcp_packet) 180 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) 181 ) { 182 DEBUG("Unrelated/bogus packet"); 197 183 return -2; 198 184 } … … 202 188 packet.ip.check = 0; 203 189 if (check != udhcp_checksum(&(packet.ip), sizeof(packet.ip))) { 204 DEBUG( LOG_INFO,"bad IP header checksum, ignoring");190 DEBUG("bad IP header checksum, ignoring"); 205 191 return -1; 206 192 } … … 218 204 packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */ 219 205 if (check && check != udhcp_checksum(&packet, bytes)) { 220 DEBUG(LOG_ERR,"packet with bad UDP checksum received, ignoring");206 bb_error_msg("packet with bad UDP checksum received, ignoring"); 221 207 return -2; 222 208 } … … 225 211 226 212 if (ntohl(payload->cookie) != DHCP_MAGIC) { 227 LOG(LOG_ERR, "received bogus message (bad magic) -- ignoring");228 return -2; 229 } 230 DEBUG( LOG_INFO,"oooooh!!! got some!");213 bb_error_msg("received bogus message (bad magic) - ignoring"); 214 return -2; 215 } 216 DEBUG("oooooh!!! got some!"); 231 217 return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); 232 233 } 218 } -
branches/stable/mindi-busybox/networking/udhcp/clientsocket.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * clientsocket.c -- DHCP client socket creation … … 21 22 */ 22 23 23 #include <sys/types.h>24 #include <sys/socket.h>25 #include <unistd.h>26 #include <netinet/in.h>27 24 #include <features.h> 28 #if ( __GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION25 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) 29 26 #include <netpacket/packet.h> 30 27 #include <net/ethernet.h> … … 35 32 #endif 36 33 37 #include "clientsocket.h"38 34 #include "common.h" 39 35 … … 44 40 struct sockaddr_ll sock; 45 41 46 DEBUG(LOG_INFO, "Opening raw socket on ifindex %d", ifindex); 47 if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { 48 DEBUG(LOG_ERR, "socket call failed: %m"); 49 return -1; 50 } 42 DEBUG("Opening raw socket on ifindex %d", ifindex); 43 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 51 44 52 45 sock.sll_family = AF_PACKET; 53 46 sock.sll_protocol = htons(ETH_P_IP); 54 47 sock.sll_ifindex = ifindex; 55 if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) { 56 DEBUG(LOG_ERR, "bind call failed: %m"); 57 close(fd); 58 return -1; 59 } 48 xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); 60 49 61 50 return fd; -
branches/stable/mindi-busybox/networking/udhcp/common.c
r821 r1770 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* common.c 3 *4 * Functions for debugging and logging as well as some other5 * simple helper functions.6 *7 * Russ Dill <Russ.Dill@asu.edu> 2001-20038 * Rewritten by Vladimir Oleynik <dzo@simtreas.ru> (C) 20039 3 * 10 4 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 11 5 */ 12 6 13 #include <fcntl.h> 14 #include <unistd.h> 15 #include <errno.h> 16 #include <string.h> 17 #include <stdlib.h> 18 #include <signal.h> 19 #include <paths.h> 20 #include <sys/socket.h> 21 #include <stdarg.h> 7 #include "common.h" 22 8 23 #include "common.h" 24 #include "pidfile.h" 25 26 27 static int daemonized; 28 29 long uptime(void) 30 { 31 struct sysinfo info; 32 sysinfo(&info); 33 return info.uptime; 34 } 35 36 37 /* 38 * This function makes sure our first socket calls 39 * aren't going to fd 1 (printf badness...) and are 40 * not later closed by daemon() 41 */ 42 static inline void sanitize_fds(void) 43 { 44 int zero; 45 if ((zero = open(bb_dev_null, O_RDWR, 0)) < 0) 46 return; 47 while (zero < 3) 48 zero = dup(zero); 49 close(zero); 50 } 51 52 53 void udhcp_background(const char *pidfile) 54 { 55 #ifdef __uClinux__ 56 LOG(LOG_ERR, "Cannot background in uclinux (yet)"); 57 #else /* __uClinux__ */ 58 int pid_fd; 59 60 /* hold lock during fork. */ 61 pid_fd = pidfile_acquire(pidfile); 62 if (daemon(0, 0) == -1) { /* bb_xdaemon? */ 63 perror("fork"); 64 exit(1); 65 } 66 daemonized++; 67 pidfile_write_release(pid_fd); 68 #endif /* __uClinux__ */ 69 } 70 71 72 #ifdef CONFIG_FEATURE_UDHCP_SYSLOG 73 74 void udhcp_logging(int level, const char *fmt, ...) 75 { 76 va_list p; 77 va_list p2; 78 79 va_start(p, fmt); 80 __va_copy(p2, p); 81 if (!daemonized) { 82 vprintf(fmt, p); 83 putchar('\n'); 84 } 85 vsyslog(level, fmt, p2); 86 va_end(p); 87 } 88 89 #else 90 91 92 static char *syslog_level_msg[] = { 93 [LOG_EMERG] = "EMERGENCY!", 94 [LOG_ALERT] = "ALERT!", 95 [LOG_CRIT] = "critical!", 96 [LOG_WARNING] = "warning", 97 [LOG_ERR] = "error", 98 [LOG_INFO] = "info", 99 [LOG_DEBUG] = "debug" 9 const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = { 10 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 100 11 }; 101 102 103 void udhcp_logging(int level, const char *fmt, ...)104 {105 va_list p;106 107 va_start(p, fmt);108 if (!daemonized) {109 printf("%s, ", syslog_level_msg[level]);110 vprintf(fmt, p);111 putchar('\n');112 }113 va_end(p);114 }115 #endif116 117 118 void udhcp_start_log_and_pid(const char *client_server, const char *pidfile)119 {120 int pid_fd;121 122 /* Make sure our syslog fd isn't overwritten */123 sanitize_fds();124 125 /* do some other misc startup stuff while we are here to save bytes */126 pid_fd = pidfile_acquire(pidfile);127 pidfile_write_release(pid_fd);128 129 /* equivelent of doing a fflush after every \n */130 setlinebuf(stdout);131 132 if (ENABLE_FEATURE_UDHCP_SYSLOG)133 openlog(client_server, LOG_PID | LOG_CONS, LOG_LOCAL0);134 135 udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, BB_VER);136 } -
branches/stable/mindi-busybox/networking/udhcp/common.h
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* common.h 2 3 * … … 10 11 #define _COMMON_H 11 12 12 #include "libbb_udhcp.h" 13 #include "libbb.h" 14 15 #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" 16 17 extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */ 18 19 /*** packet.h ***/ 20 21 #include <netinet/udp.h> 22 #include <netinet/ip.h> 23 24 struct dhcpMessage { 25 uint8_t op; 26 uint8_t htype; 27 uint8_t hlen; 28 uint8_t hops; 29 uint32_t xid; 30 uint16_t secs; 31 uint16_t flags; 32 uint32_t ciaddr; 33 uint32_t yiaddr; 34 uint32_t siaddr; 35 uint32_t giaddr; 36 uint8_t chaddr[16]; 37 uint8_t sname[64]; 38 uint8_t file[128]; 39 uint32_t cookie; 40 uint8_t options[308]; /* 312 - cookie */ 41 }; 42 43 struct udp_dhcp_packet { 44 struct iphdr ip; 45 struct udphdr udp; 46 struct dhcpMessage data; 47 }; 48 49 void udhcp_init_header(struct dhcpMessage *packet, char type); 50 int udhcp_get_packet(struct dhcpMessage *packet, int fd); 51 uint16_t udhcp_checksum(void *addr, int count); 52 int udhcp_raw_packet(struct dhcpMessage *payload, 53 uint32_t source_ip, int source_port, 54 uint32_t dest_ip, int dest_port, 55 const uint8_t *dest_arp, int ifindex); 56 int udhcp_kernel_packet(struct dhcpMessage *payload, 57 uint32_t source_ip, int source_port, 58 uint32_t dest_ip, int dest_port); 13 59 14 60 15 enum syslog_levels { 16 LOG_EMERG = 0, 17 LOG_ALERT, 18 LOG_CRIT, 19 LOG_WARNING, 20 LOG_ERR, 21 LOG_INFO, 22 LOG_DEBUG 23 }; 24 #include <syslog.h> 61 /**/ 25 62 26 long uptime(void);63 void udhcp_run_script(struct dhcpMessage *packet, const char *name); 27 64 28 #define LOG(level, str, args...) udhcp_logging(level, str, ## args) 65 // Still need to clean these up... 66 67 /* from options.h */ 68 #define get_option udhcp_get_option 69 #define end_option udhcp_end_option 70 #define add_option_string udhcp_add_option_string 71 #define add_simple_option udhcp_add_simple_option 72 #define option_lengths udhcp_option_lengths 73 /* from socket.h */ 74 #define listen_socket udhcp_listen_socket 75 #define read_interface udhcp_read_interface 76 /* from dhcpc.h */ 77 #define client_config udhcp_client_config 78 /* from dhcpd.h */ 79 #define server_config udhcp_server_config 80 81 void udhcp_sp_setup(void); 82 int udhcp_sp_fd_set(fd_set *rfds, int extra_fd); 83 int udhcp_sp_read(fd_set *rfds); 84 int raw_socket(int ifindex); 85 int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp); 86 int listen_socket(/*uint32_t ip,*/ int port, const char *inf); 87 /* Returns 1 if no reply received */ 88 int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface); 29 89 30 90 #if ENABLE_FEATURE_UDHCP_DEBUG 31 # define DEBUG( level, str, args...) LOG(level,str, ## args)91 # define DEBUG(str, args...) bb_info_msg(str, ## args) 32 92 #else 33 # define DEBUG( level, str, args...) do {;} while(0)93 # define DEBUG(str, args...) do {;} while (0) 34 94 #endif 35 95 -
branches/stable/mindi-busybox/networking/udhcp/dhcpc.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* dhcpc.c 2 3 * … … 8 9 */ 9 10 10 #include <sys/file.h>11 #include <unistd.h>12 11 #include <getopt.h> 13 #include <stdlib.h> 14 #include <sys/socket.h> 15 #include <netinet/in.h> 16 #include <arpa/inet.h> 17 #include <signal.h> 18 #include <time.h> 19 #include <string.h> 20 #include <sys/ioctl.h> 21 #include <net/if.h> 22 #include <errno.h> 23 12 #include <syslog.h> 13 14 /* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */ 15 #define WANT_PIDFILE 1 24 16 #include "common.h" 25 17 #include "dhcpd.h" 26 18 #include "dhcpc.h" 27 19 #include "options.h" 28 #include "clientpacket.h" 29 #include "clientsocket.h" 30 #include "socket.h" 31 #include "signalpipe.h" 32 33 static int state; 34 static unsigned long requested_ip; /* = 0 */ 35 static unsigned long server_addr; 36 static unsigned long timeout; 20 21 22 /* Something is definitely wrong here. IPv4 addresses 23 * in variables of type long?? BTW, we use inet_ntoa() 24 * in the code. Manpage says that struct in_addr has a member of type long (!) 25 * which holds IPv4 address, and the struct is passed by value (!!) 26 */ 27 static unsigned timeout; 28 static uint32_t requested_ip; /* = 0 */ 29 static uint32_t server_addr; 37 30 static int packet_num; /* = 0 */ 38 static int fd = -1;31 static int sockfd = -1; 39 32 40 33 #define LISTEN_NONE 0 41 34 #define LISTEN_KERNEL 1 42 35 #define LISTEN_RAW 2 43 static int listen_mode; 44 45 struct client_config_t client_config = { 46 /* Default options. */ 47 .abort_if_no_lease = 0, 48 .foreground = 0, 49 .quit_after_lease = 0, 50 .background_if_no_lease = 0, 51 .interface = "eth0", 52 .pidfile = NULL, 53 .script = DEFAULT_SCRIPT, 54 .clientid = NULL, 55 .vendorclass = NULL, 56 .hostname = NULL, 57 .fqdn = NULL, 58 .ifindex = 0, 59 .retries = 3, 60 .timeout = 3, 61 .arp = "\0\0\0\0\0\0", /* appease gcc-3.0 */ 62 }; 36 static smallint listen_mode; 37 38 static smallint state; 39 40 struct client_config_t client_config; 41 63 42 64 43 /* just a little helper */ 65 44 static void change_mode(int new_mode) 66 45 { 67 DEBUG( LOG_INFO,"entering %s listen mode",46 DEBUG("entering %s listen mode", 68 47 new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); 69 if (fd >= 0) close(fd); 70 fd = -1; 48 if (sockfd >= 0) { 49 close(sockfd); 50 sockfd = -1; 51 } 71 52 listen_mode = new_mode; 72 53 } … … 76 57 static void perform_renew(void) 77 58 { 78 LOG(LOG_INFO,"Performing a DHCP renew");59 bb_info_msg("Performing a DHCP renew"); 79 60 switch (state) { 80 61 case BOUND: … … 106 87 static void perform_release(void) 107 88 { 108 char buffer[ 16];89 char buffer[sizeof("255.255.255.255")]; 109 90 struct in_addr temp_addr; 110 91 … … 112 93 if (state == BOUND || state == RENEWING || state == REBINDING) { 113 94 temp_addr.s_addr = server_addr; 114 s printf(buffer, "%s", inet_ntoa(temp_addr));95 strcpy(buffer, inet_ntoa(temp_addr)); 115 96 temp_addr.s_addr = requested_ip; 116 LOG(LOG_INFO,"Unicasting a release of %s to %s",97 bb_info_msg("Unicasting a release of %s to %s", 117 98 inet_ntoa(temp_addr), buffer); 118 99 send_release(server_addr, requested_ip); /* unicast */ 119 100 udhcp_run_script(NULL, "deconfig"); 120 101 } 121 LOG(LOG_INFO,"Entering released state");102 bb_info_msg("Entering released state"); 122 103 123 104 change_mode(LISTEN_NONE); 124 105 state = RELEASED; 125 timeout = 0x7fffffff;106 timeout = INT_MAX; 126 107 } 127 108 … … 129 110 static void client_background(void) 130 111 { 131 udhcp_background(client_config.pidfile); 132 client_config.foreground = 1; /* Do not fork again. */ 112 #if !BB_MMU 113 bb_error_msg("cannot background in uclinux (yet)"); 114 /* ... mainly because udhcpc calls client_background() 115 * in _the _middle _of _udhcpc _run_, not at the start! 116 * If that will be properly disabled for NOMMU, client_background() 117 * will work on NOMMU too */ 118 #else 119 bb_daemonize(0); 120 logmode &= ~LOGMODE_STDIO; 121 /* rewrite pidfile, as our pid is different now */ 122 write_pidfile(client_config.pidfile); 123 #endif 124 /* Do not fork again. */ 125 client_config.foreground = 1; 133 126 client_config.background_if_no_lease = 0; 134 127 } 135 128 136 129 137 int udhcpc_main(int argc, char *argv[]) 130 static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) 131 { 132 uint8_t *storage; 133 int len = strlen(str); 134 if (len > 255) len = 255; 135 storage = xzalloc(len + extra + OPT_DATA); 136 storage[OPT_CODE] = code; 137 storage[OPT_LEN] = len + extra; 138 memcpy(storage + extra + OPT_DATA, str, len); 139 return storage; 140 } 141 142 143 int udhcpc_main(int argc, char **argv); 144 int udhcpc_main(int argc, char **argv) 138 145 { 139 146 uint8_t *temp, *message; 140 unsigned long t1 = 0, t2 = 0, xid = 0; 141 unsigned long start = 0, lease; 147 char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t; 148 uint32_t xid = 0; 149 uint32_t lease = 0; /* can be given as 32-bit quantity */ 150 unsigned t1 = 0, t2 = 0; /* what a wonderful names */ 151 unsigned start = 0; 152 unsigned now; 153 unsigned opt; 154 int max_fd; 155 int retval; 156 int len; 157 struct timeval tv; 158 struct in_addr temp_addr; 159 struct dhcpMessage packet; 142 160 fd_set rfds; 143 int retval; 144 struct timeval tv; 145 int c, len; 146 struct dhcpMessage packet; 147 struct in_addr temp_addr; 148 long now; 149 int max_fd; 150 int sig; 151 int no_clientid = 0; 152 153 static const struct option arg_options[] = { 154 {"clientid", required_argument, 0, 'c'}, 155 {"clientid-none", no_argument, 0, 'C'}, 156 {"vendorclass", required_argument, 0, 'V'}, 157 {"foreground", no_argument, 0, 'f'}, 158 {"background", no_argument, 0, 'b'}, 159 {"hostname", required_argument, 0, 'H'}, 160 {"hostname", required_argument, 0, 'h'}, 161 {"fqdn", required_argument, 0, 'F'}, 162 {"interface", required_argument, 0, 'i'}, 163 {"now", no_argument, 0, 'n'}, 164 {"pidfile", required_argument, 0, 'p'}, 165 {"quit", no_argument, 0, 'q'}, 166 {"request", required_argument, 0, 'r'}, 167 {"script", required_argument, 0, 's'}, 168 {"timeout", required_argument, 0, 'T'}, 169 {"version", no_argument, 0, 'v'}, 170 {"retries", required_argument, 0, 't'}, 171 {0, 0, 0, 0} 161 162 enum { 163 OPT_c = 1 << 0, 164 OPT_C = 1 << 1, 165 OPT_V = 1 << 2, 166 OPT_f = 1 << 3, 167 OPT_b = 1 << 4, 168 OPT_H = 1 << 5, 169 OPT_h = 1 << 6, 170 OPT_F = 1 << 7, 171 OPT_i = 1 << 8, 172 OPT_n = 1 << 9, 173 OPT_p = 1 << 10, 174 OPT_q = 1 << 11, 175 OPT_R = 1 << 12, 176 OPT_r = 1 << 13, 177 OPT_s = 1 << 14, 178 OPT_T = 1 << 15, 179 OPT_t = 1 << 16, 180 OPT_v = 1 << 17, 181 OPT_S = 1 << 18, 172 182 }; 173 174 /* get options */ 175 while (1) { 176 int option_index = 0; 177 c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qr:s:T:t:v", arg_options, &option_index); 178 if (c == -1) break; 179 180 switch (c) { 181 case 'c': 182 if (no_clientid) bb_show_usage(); 183 len = strlen(optarg) > 255 ? 255 : strlen(optarg); 184 free(client_config.clientid); 185 client_config.clientid = xmalloc(len + 2); 186 client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; 187 client_config.clientid[OPT_LEN] = len; 188 client_config.clientid[OPT_DATA] = '\0'; 189 strncpy((char*)client_config.clientid + OPT_DATA, optarg, len); 190 break; 191 case 'C': 192 if (client_config.clientid) bb_show_usage(); 193 no_clientid = 1; 194 break; 195 case 'V': 196 len = strlen(optarg) > 255 ? 255 : strlen(optarg); 197 free(client_config.vendorclass); 198 client_config.vendorclass = xmalloc(len + 2); 199 client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; 200 client_config.vendorclass[OPT_LEN] = len; 201 strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len); 202 break; 203 case 'f': 204 client_config.foreground = 1; 205 break; 206 case 'b': 207 client_config.background_if_no_lease = 1; 208 break; 209 case 'h': 210 case 'H': 211 len = strlen(optarg) > 255 ? 255 : strlen(optarg); 212 free(client_config.hostname); 213 client_config.hostname = xmalloc(len + 2); 214 client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; 215 client_config.hostname[OPT_LEN] = len; 216 strncpy((char*)client_config.hostname + 2, optarg, len); 217 break; 218 case 'F': 219 len = strlen(optarg) > 255 ? 255 : strlen(optarg); 220 free(client_config.fqdn); 221 client_config.fqdn = xmalloc(len + 5); 222 client_config.fqdn[OPT_CODE] = DHCP_FQDN; 223 client_config.fqdn[OPT_LEN] = len + 3; 224 /* Flags: 0000NEOS 225 S: 1 => Client requests Server to update A RR in DNS as well as PTR 226 O: 1 => Server indicates to client that DNS has been updated regardless 227 E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" 228 N: 1 => Client requests Server to not update DNS 229 */ 230 client_config.fqdn[OPT_LEN + 1] = 0x1; 231 client_config.fqdn[OPT_LEN + 2] = 0; 232 client_config.fqdn[OPT_LEN + 3] = 0; 233 strncpy((char*)client_config.fqdn + 5, optarg, len); 234 break; 235 case 'i': 236 client_config.interface = optarg; 237 break; 238 case 'n': 239 client_config.abort_if_no_lease = 1; 240 break; 241 case 'p': 242 client_config.pidfile = optarg; 243 break; 244 case 'q': 245 client_config.quit_after_lease = 1; 246 break; 247 case 'r': 248 requested_ip = inet_addr(optarg); 249 break; 250 case 's': 251 client_config.script = optarg; 252 break; 253 case 'T': 254 client_config.timeout = atoi(optarg); 255 break; 256 case 't': 257 client_config.retries = atoi(optarg); 258 break; 259 case 'v': 260 printf("version %s\n\n", BB_VER); 261 return 0; 262 break; 263 default: 264 bb_show_usage(); 265 } 266 } 267 268 /* Start the log, sanitize fd's, and write a pid file */ 269 udhcp_start_log_and_pid("udhcpc", client_config.pidfile); 183 #if ENABLE_GETOPT_LONG 184 static const char udhcpc_longopts[] ALIGN1 = 185 "clientid\0" Required_argument "c" 186 "clientid-none\0" No_argument "C" 187 "vendorclass\0" Required_argument "V" 188 "foreground\0" No_argument "f" 189 "background\0" No_argument "b" 190 "hostname\0" Required_argument "H" 191 "hostname\0" Required_argument "h" 192 "fqdn\0" Required_argument "F" 193 "interface\0" Required_argument "i" 194 "now\0" No_argument "n" 195 "pidfile\0" Required_argument "p" 196 "quit\0" No_argument "q" 197 "release\0" No_argument "R" 198 "request\0" Required_argument "r" 199 "script\0" Required_argument "s" 200 "timeout\0" Required_argument "T" 201 "version\0" No_argument "v" 202 "retries\0" Required_argument "t" 203 "syslog\0" No_argument "S" 204 ; 205 #endif 206 /* Default options. */ 207 client_config.interface = "eth0"; 208 client_config.script = DEFAULT_SCRIPT; 209 client_config.retries = 3; 210 client_config.timeout = 3; 211 212 /* Parse command line */ 213 opt_complementary = "c--C:C--c" // mutually exclusive 214 ":hH:Hh"; // -h and -H are the same 215 #if ENABLE_GETOPT_LONG 216 applet_long_options = udhcpc_longopts; 217 #endif 218 opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vS", 219 &str_c, &str_V, &str_h, &str_h, &str_F, 220 &client_config.interface, &client_config.pidfile, &str_r, 221 &client_config.script, &str_T, &str_t 222 ); 223 224 if (opt & OPT_c) 225 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0); 226 //if (opt & OPT_C) 227 if (opt & OPT_V) 228 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); 229 if (opt & OPT_f) 230 client_config.foreground = 1; 231 if (opt & OPT_b) 232 client_config.background_if_no_lease = 1; 233 if (opt & OPT_h) 234 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); 235 if (opt & OPT_F) { 236 client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); 237 /* Flags: 0000NEOS 238 S: 1 => Client requests Server to update A RR in DNS as well as PTR 239 O: 1 => Server indicates to client that DNS has been updated regardless 240 E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" 241 N: 1 => Client requests Server to not update DNS 242 */ 243 client_config.fqdn[OPT_DATA + 0] = 0x1; 244 /* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */ 245 /* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */ 246 } 247 // if (opt & OPT_i) client_config.interface = ... 248 if (opt & OPT_n) 249 client_config.abort_if_no_lease = 1; 250 // if (opt & OPT_p) client_config.pidfile = ... 251 if (opt & OPT_q) 252 client_config.quit_after_lease = 1; 253 if (opt & OPT_R) 254 client_config.release_on_quit = 1; 255 if (opt & OPT_r) 256 requested_ip = inet_addr(str_r); 257 // if (opt & OPT_s) client_config.script = ... 258 if (opt & OPT_T) 259 client_config.timeout = xatoi_u(str_T); 260 if (opt & OPT_t) 261 client_config.retries = xatoi_u(str_t); 262 if (opt & OPT_v) { 263 printf("version %s\n", BB_VER); 264 return 0; 265 } 266 267 if (opt & OPT_S) { 268 openlog(applet_name, LOG_PID, LOG_LOCAL0); 269 logmode |= LOGMODE_SYSLOG; 270 } 270 271 271 272 if (read_interface(client_config.interface, &client_config.ifindex, 272 NULL, client_config.arp) < 0)273 NULL, client_config.arp)) 273 274 return 1; 274 275 276 /* Make sure fd 0,1,2 are open */ 277 bb_sanitize_stdio(); 278 /* Equivalent of doing a fflush after every \n */ 279 setlinebuf(stdout); 280 281 /* Create pidfile */ 282 write_pidfile(client_config.pidfile); 283 /* if (!..) bb_perror_msg("cannot create pidfile %s", pidfile); */ 284 285 /* Goes to stdout and possibly syslog */ 286 bb_info_msg("%s (v%s) started", applet_name, BB_VER); 287 275 288 /* if not set, and not suppressed, setup the default client ID */ 276 if (!client_config.clientid && !no_clientid) { 277 client_config.clientid = xmalloc(6 + 3); 278 client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; 279 client_config.clientid[OPT_LEN] = 7; 289 if (!client_config.clientid && !(opt & OPT_C)) { 290 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); 280 291 client_config.clientid[OPT_DATA] = 1; 281 memcpy(client_config.clientid + 3, client_config.arp, 6); 282 } 283 284 if (!client_config.vendorclass) { 285 client_config.vendorclass = xmalloc(sizeof("udhcp "BB_VER) + 2); 286 client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; 287 client_config.vendorclass[OPT_LEN] = sizeof("udhcp "BB_VER) - 1; 288 client_config.vendorclass[OPT_DATA] = 1; 289 memcpy(&client_config.vendorclass[OPT_DATA], 290 "udhcp "BB_VER, sizeof("udhcp "BB_VER) - 1); 291 } 292 292 memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6); 293 } 294 295 if (!client_config.vendorclass) 296 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0); 293 297 294 298 /* setup the signal pipe */ … … 298 302 udhcp_run_script(NULL, "deconfig"); 299 303 change_mode(LISTEN_RAW); 304 tv.tv_sec = 0; 305 goto jump_in; 300 306 301 307 for (;;) { 302 303 tv.tv_sec = timeout - uptime(); 308 tv.tv_sec = timeout - monotonic_sec(); 309 jump_in: 304 310 tv.tv_usec = 0; 305 311 306 if (listen_mode != LISTEN_NONE && fd < 0) {312 if (listen_mode != LISTEN_NONE && sockfd < 0) { 307 313 if (listen_mode == LISTEN_KERNEL) 308 fd = listen_socket(INADDR_ANY,CLIENT_PORT, client_config.interface);314 sockfd = listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface); 309 315 else 310 fd = raw_socket(client_config.ifindex); 311 if (fd < 0) { 312 LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m"); 313 return 0; 314 } 316 sockfd = raw_socket(client_config.ifindex); 315 317 } 316 max_fd = udhcp_sp_fd_set(&rfds, fd); 317 318 max_fd = udhcp_sp_fd_set(&rfds, sockfd); 319 320 retval = 0; /* If we already timed out, fall through, else... */ 318 321 if (tv.tv_sec > 0) { 319 DEBUG( LOG_INFO,"Waiting on select...");322 DEBUG("Waiting on select..."); 320 323 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 321 } else retval = 0; /* If we already timed out, fall through */ 322 323 now = uptime(); 324 if (retval == 0) { 324 } 325 326 now = monotonic_sec(); 327 if (retval < 0) { 328 /* EINTR? signal was caught, don't panic */ 329 if (errno != EINTR) { 330 /* Else: an error occured, panic! */ 331 bb_perror_msg_and_die("select"); 332 } 333 } else if (retval == 0) { 325 334 /* timeout dropped to zero */ 326 335 switch (state) { … … 338 347 udhcp_run_script(NULL, "leasefail"); 339 348 if (client_config.background_if_no_lease) { 340 LOG(LOG_INFO, "No lease, forking to background.");349 bb_info_msg("No lease, forking to background"); 341 350 client_background(); 342 351 } else if (client_config.abort_if_no_lease) { 343 LOG(LOG_INFO, "No lease, failing."); 344 return 1; 352 bb_info_msg("No lease, failing"); 353 retval = 1; 354 goto ret; 345 355 } 346 356 /* wait to try again */ … … 361 371 } else { 362 372 /* timed out, go back to init state */ 363 if (state == RENEW_REQUESTED) udhcp_run_script(NULL, "deconfig"); 373 if (state == RENEW_REQUESTED) 374 udhcp_run_script(NULL, "deconfig"); 364 375 state = INIT_SELECTING; 365 376 timeout = now; … … 372 383 state = RENEWING; 373 384 change_mode(LISTEN_KERNEL); 374 DEBUG( LOG_INFO,"Entering renew state");385 DEBUG("Entering renew state"); 375 386 /* fall right through */ 376 387 case RENEWING: … … 380 391 state = REBINDING; 381 392 timeout = now + (t2 - t1); 382 DEBUG( LOG_INFO,"Entering rebinding state");393 DEBUG("Entering rebinding state"); 383 394 } else { 384 395 /* send a request packet */ 385 396 send_renew(xid, server_addr, requested_ip); /* unicast */ 386 387 397 t1 = (t2 - t1) / 2 + t1; 388 timeout = t1 + start;398 timeout = start + t1; 389 399 } 390 400 break; … … 394 404 /* timed out, enter init state */ 395 405 state = INIT_SELECTING; 396 LOG(LOG_INFO,"Lease lost, entering init state");406 bb_info_msg("Lease lost, entering init state"); 397 407 udhcp_run_script(NULL, "deconfig"); 398 408 timeout = now; … … 402 412 /* send a request packet */ 403 413 send_renew(xid, 0, requested_ip); /* broadcast */ 404 405 414 t2 = (lease - t2) / 2 + t2; 406 timeout = t2 + start;415 timeout = start + t2; 407 416 } 408 417 break; 409 418 case RELEASED: 410 419 /* yah, I know, *you* say it would never happen */ 411 timeout = 0x7fffffff;412 break; 413 } 414 } else if ( retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {420 timeout = INT_MAX; 421 break; 422 } 423 } else if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) { 415 424 /* a packet is ready, read it */ 416 425 417 426 if (listen_mode == LISTEN_KERNEL) 418 len = udhcp_get_packet(&packet, fd);419 else len = get_raw_packet(&packet, fd);427 len = udhcp_get_packet(&packet, sockfd); 428 else len = get_raw_packet(&packet, sockfd); 420 429 421 430 if (len == -1 && errno != EINTR) { 422 DEBUG( LOG_INFO, "error on read, %m, reopening socket");431 DEBUG("error on read, %s, reopening socket", strerror(errno)); 423 432 change_mode(listen_mode); /* just close and reopen */ 424 433 } … … 426 435 427 436 if (packet.xid != xid) { 428 DEBUG( LOG_INFO, "Ignoring XID %lx (our xid is %lx)",429 (unsigned long) packet.xid,xid);437 DEBUG("Ignoring XID %x (our xid is %x)", 438 (unsigned)packet.xid, (unsigned)xid); 430 439 continue; 431 440 } … … 433 442 /* Ignore packets that aren't for us */ 434 443 if (memcmp(packet.chaddr, client_config.arp, 6)) { 435 DEBUG( LOG_INFO, "packet does not have our chaddr -- ignoring");444 DEBUG("Packet does not have our chaddr - ignoring"); 436 445 continue; 437 446 } 438 447 439 if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { 440 DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); 448 message = get_option(&packet, DHCP_MESSAGE_TYPE); 449 if (message == NULL) { 450 bb_error_msg("cannot get option from packet - ignoring"); 441 451 continue; 442 452 } … … 446 456 /* Must be a DHCPOFFER to one of our xid's */ 447 457 if (*message == DHCPOFFER) { 448 if ((temp = get_option(&packet, DHCP_SERVER_ID))) { 458 temp = get_option(&packet, DHCP_SERVER_ID); 459 if (temp) { 460 /* can be misaligned, thus memcpy */ 449 461 memcpy(&server_addr, temp, 4); 450 462 xid = packet.xid; … … 456 468 packet_num = 0; 457 469 } else { 458 DEBUG(LOG_ERR, "No server ID in message");470 bb_error_msg("no server ID in message"); 459 471 } 460 472 } … … 465 477 case REBINDING: 466 478 if (*message == DHCPACK) { 467 if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { 468 LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease"); 479 temp = get_option(&packet, DHCP_LEASE_TIME); 480 if (!temp) { 481 bb_error_msg("no lease time with ACK, using 1 hour lease"); 469 482 lease = 60 * 60; 470 483 } else { 484 /* can be misaligned, thus memcpy */ 471 485 memcpy(&lease, temp, 4); 472 486 lease = ntohl(lease); … … 477 491 478 492 /* little fixed point for n * .875 */ 479 t2 = (lease * 0x7) >> 3;493 t2 = (lease * 7) >> 3; 480 494 temp_addr.s_addr = packet.yiaddr; 481 LOG(LOG_INFO, "Lease of %s obtained, lease time %ld",482 inet_ntoa(temp_addr), lease);495 bb_info_msg("Lease of %s obtained, lease time %u", 496 inet_ntoa(temp_addr), (unsigned)lease); 483 497 start = now; 484 timeout = t1 + start;498 timeout = start + t1; 485 499 requested_ip = packet.yiaddr; 486 500 udhcp_run_script(&packet, … … 489 503 state = BOUND; 490 504 change_mode(LISTEN_NONE); 491 if (client_config.quit_after_lease) 492 return 0; 505 if (client_config.quit_after_lease) { 506 if (client_config.release_on_quit) 507 perform_release(); 508 goto ret0; 509 } 493 510 if (!client_config.foreground) 494 511 client_background(); … … 496 513 } else if (*message == DHCPNAK) { 497 514 /* return to init state */ 498 LOG(LOG_INFO,"Received DHCP NAK");515 bb_info_msg("Received DHCP NAK"); 499 516 udhcp_run_script(&packet, "nak"); 500 517 if (state != REQUESTING) … … 510 527 /* case BOUND, RELEASED: - ignore all packets */ 511 528 } 512 } else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) { 513 switch (sig) { 529 } else { 530 int signo = udhcp_sp_read(&rfds); 531 switch (signo) { 514 532 case SIGUSR1: 515 533 perform_renew(); … … 519 537 break; 520 538 case SIGTERM: 521 LOG(LOG_INFO, "Received SIGTERM"); 522 return 0; 523 } 524 } else if (retval == -1 && errno == EINTR) { 525 /* a signal was caught */ 526 } else { 527 /* An error occured */ 528 DEBUG(LOG_ERR, "Error on select"); 539 bb_info_msg("Received SIGTERM"); 540 if (client_config.release_on_quit) 541 perform_release(); 542 goto ret0; 543 } 529 544 } 530 531 } 532 return 0; 545 } /* for (;;) */ 546 ret0: 547 retval = 0; 548 ret: 549 /*if (client_config.pidfile) - remove_pidfile has it's own check */ 550 remove_pidfile(client_config.pidfile); 551 return retval; 533 552 } -
branches/stable/mindi-busybox/networking/udhcp/dhcpc.h
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* dhcpc.h */ 2 3 #ifndef _DHCPC_H 3 4 #define _DHCPC_H 4 5 /* grab define DEFAULT_SCRIPT */6 #include "libbb_udhcp.h"7 5 8 6 #define INIT_SELECTING 0 … … 15 13 #define RELEASED 7 16 14 17 18 15 struct client_config_t { 19 char foreground; /* Do not fork */ 20 char quit_after_lease; /* Quit after obtaining lease */ 21 char abort_if_no_lease; /* Abort if no lease */ 22 char background_if_no_lease; /* Fork to background if no lease */ 23 char *interface; /* The name of the interface to use */ 24 char *pidfile; /* Optionally store the process ID */ 25 char *script; /* User script to run at dhcp events */ 26 uint8_t *clientid; /* Optional client id to use */ 27 uint8_t *vendorclass; /* Optional vendor class-id to use */ 28 uint8_t *hostname; /* Optional hostname to use */ 29 uint8_t *fqdn; /* Optional fully qualified domain name to use */ 30 int ifindex; /* Index number of the interface to use */ 31 int retries; /* Max number of request packets */ 32 int timeout; /* Number of seconds to try to get a lease */ 33 uint8_t arp[6]; /* Our arp address */ 16 /* TODO: combine flag fields into single "unsigned opt" */ 17 /* (can be set directly to the result of getopt32) */ 18 char foreground; /* Do not fork */ 19 char quit_after_lease; /* Quit after obtaining lease */ 20 char release_on_quit; /* Perform release on quit */ 21 char abort_if_no_lease; /* Abort if no lease */ 22 char background_if_no_lease; /* Fork to background if no lease */ 23 const char *interface; /* The name of the interface to use */ 24 char *pidfile; /* Optionally store the process ID */ 25 const char *script; /* User script to run at dhcp events */ 26 uint8_t *clientid; /* Optional client id to use */ 27 uint8_t *vendorclass; /* Optional vendor class-id to use */ 28 uint8_t *hostname; /* Optional hostname to use */ 29 uint8_t *fqdn; /* Optional fully qualified domain name to use */ 30 int ifindex; /* Index number of the interface to use */ 31 int retries; /* Max number of request packets */ 32 int timeout; /* Number of seconds to try to get a lease */ 33 uint8_t arp[6]; /* Our arp address */ 34 34 }; 35 35 … … 37 37 38 38 39 /*** clientpacket.h ***/ 40 41 uint32_t random_xid(void); 42 int send_discover(uint32_t xid, uint32_t requested); 43 int send_selecting(uint32_t xid, uint32_t server, uint32_t requested); 44 int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr); 45 int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr); 46 int send_release(uint32_t server, uint32_t ciaddr); 47 int get_raw_packet(struct dhcpMessage *payload, int fd); 48 49 39 50 #endif -
branches/stable/mindi-busybox/networking/udhcp/dhcpd.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* dhcpd.c 2 3 * … … 10 11 */ 11 12 12 #include <fcntl.h> 13 #include <string.h> 14 #include <stdlib.h> 15 #include <sys/wait.h> 16 #include <arpa/inet.h> 17 #include <netdb.h> 18 #include <netinet/in.h> 19 #include <sys/socket.h> 20 #include <unistd.h> 21 #include <signal.h> 22 #include <errno.h> 23 #include <sys/ioctl.h> 24 #include <time.h> 25 13 #include <syslog.h> 14 #include "common.h" 26 15 #include "dhcpd.h" 27 #include "arpping.h"28 #include "socket.h"29 16 #include "options.h" 30 #include "files.h"31 #include "serverpacket.h"32 #include "common.h"33 #include "signalpipe.h"34 #include "static_leases.h"35 17 36 18 … … 40 22 41 23 42 int udhcpd_main(int argc, char *argv[]) 24 int udhcpd_main(int argc, char **argv); 25 int udhcpd_main(int argc, char **argv) 43 26 { 44 27 fd_set rfds; … … 48 31 uint8_t *state, *server_id, *requested; 49 32 uint32_t server_id_align, requested_align, static_lease_ip; 50 unsigned long timeout_end, num_ips; 33 unsigned timeout_end; 34 unsigned num_ips; 35 unsigned opt; 51 36 struct option_set *option; 52 37 struct dhcpOfferedAddr *lease, static_lease; 53 38 54 read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]); 55 56 /* Start the log, sanitize fd's, and write a pid file */ 57 udhcp_start_log_and_pid("udhcpd", server_config.pidfile); 58 59 if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { 39 opt = getopt32(argv, "fS"); 40 argv += optind; 41 42 if (!(opt & 1)) { /* no -f */ 43 bb_daemonize_or_rexec(0, argv); 44 logmode &= ~LOGMODE_STDIO; 45 } 46 47 if (opt & 2) { /* -S */ 48 openlog(applet_name, LOG_PID, LOG_LOCAL0); 49 logmode |= LOGMODE_SYSLOG; 50 } 51 52 /* Would rather not do read_config before daemonization - 53 * otherwise NOMMU machines will parse config twice */ 54 read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); 55 56 /* Make sure fd 0,1,2 are open */ 57 bb_sanitize_stdio(); 58 /* Equivalent of doing a fflush after every \n */ 59 setlinebuf(stdout); 60 61 /* Create pidfile */ 62 write_pidfile(server_config.pidfile); 63 /* if (!..) bb_perror_msg("cannot create pidfile %s", pidfile); */ 64 65 bb_info_msg("%s (v%s) started", applet_name, BB_VER); 66 67 option = find_option(server_config.options, DHCP_LEASE_TIME); 68 server_config.lease = LEASE_TIME; 69 if (option) { 60 70 memcpy(&server_config.lease, option->data + 2, 4); 61 71 server_config.lease = ntohl(server_config.lease); 62 72 } 63 else server_config.lease = LEASE_TIME;64 73 65 74 /* Sanity check */ 66 num_ips = ntohl(server_config.end) - ntohl(server_config.start)+ 1;75 num_ips = server_config.end_ip - server_config.start_ip + 1; 67 76 if (server_config.max_leases > num_ips) { 68 LOG(LOG_ERR, "max_leases value (%lu) not sane, " 69 "setting to %lu instead", 70 server_config.max_leases, num_ips); 77 bb_error_msg("max_leases=%u is too big, setting to %u", 78 (unsigned)server_config.max_leases, num_ips); 71 79 server_config.max_leases = num_ips; 72 80 } 73 81 74 leases = xzalloc(server_config.max_leases * sizeof( struct dhcpOfferedAddr));82 leases = xzalloc(server_config.max_leases * sizeof(*leases)); 75 83 read_leases(server_config.lease_file); 76 84 77 85 if (read_interface(server_config.interface, &server_config.ifindex, 78 &server_config.server, server_config.arp) < 0) 79 return 1; 80 81 if (!ENABLE_FEATURE_UDHCP_DEBUG) 82 udhcp_background(server_config.pidfile); /* hold lock during fork. */ 86 &server_config.server, server_config.arp)) { 87 retval = 1; 88 goto ret; 89 } 83 90 84 91 /* Setup the signal pipe */ 85 92 udhcp_sp_setup(); 86 93 87 timeout_end = time(0) + server_config.auto_time; 88 while(1) { /* loop until universe collapses */ 89 90 if (server_socket < 0) 91 if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { 92 LOG(LOG_ERR, "FATAL: couldn't create server socket, %m"); 93 return 2; 94 } 94 timeout_end = monotonic_sec() + server_config.auto_time; 95 while (1) { /* loop until universe collapses */ 96 97 if (server_socket < 0) { 98 server_socket = listen_socket(/*INADDR_ANY,*/ SERVER_PORT, 99 server_config.interface); 100 } 95 101 96 102 max_sock = udhcp_sp_fd_set(&rfds, server_socket); 97 103 if (server_config.auto_time) { 98 tv.tv_sec = timeout_end - time(0);104 tv.tv_sec = timeout_end - monotonic_sec(); 99 105 tv.tv_usec = 0; 100 106 } 107 retval = 0; 101 108 if (!server_config.auto_time || tv.tv_sec > 0) { 102 109 retval = select(max_sock + 1, &rfds, NULL, NULL, 103 110 server_config.auto_time ? &tv : NULL); 104 } else retval = 0; /* If we already timed out, fall through */ 105 111 } 106 112 if (retval == 0) { 107 113 write_leases(); 108 timeout_end = time(0) + server_config.auto_time; 109 continue; 110 } else if (retval < 0 && errno != EINTR) { 111 DEBUG(LOG_INFO, "error on select"); 114 timeout_end = monotonic_sec() + server_config.auto_time; 115 continue; 116 } 117 if (retval < 0 && errno != EINTR) { 118 DEBUG("error on select"); 112 119 continue; 113 120 } … … 115 122 switch (udhcp_sp_read(&rfds)) { 116 123 case SIGUSR1: 117 LOG(LOG_INFO,"Received a SIGUSR1");124 bb_info_msg("Received a SIGUSR1"); 118 125 write_leases(); 119 126 /* why not just reset the timeout, eh */ 120 timeout_end = time(0) + server_config.auto_time;127 timeout_end = monotonic_sec() + server_config.auto_time; 121 128 continue; 122 129 case SIGTERM: 123 LOG(LOG_INFO,"Received a SIGTERM");124 return0;130 bb_info_msg("Received a SIGTERM"); 131 goto ret0; 125 132 case 0: break; /* no signal */ 126 133 default: continue; /* signal or error (probably EINTR) */ 127 134 } 128 135 129 if ((bytes = udhcp_get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ 136 bytes = udhcp_get_packet(&packet, server_socket); /* this waits for a packet - idle */ 137 if (bytes < 0) { 130 138 if (bytes == -1 && errno != EINTR) { 131 DEBUG( LOG_INFO, "error on read, %m, reopening socket");139 DEBUG("error on read, %s, reopening socket", strerror(errno)); 132 140 close(server_socket); 133 141 server_socket = -1; … … 136 144 } 137 145 138 if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { 139 DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); 146 state = get_option(&packet, DHCP_MESSAGE_TYPE); 147 if (state == NULL) { 148 bb_error_msg("cannot get option from packet, ignoring"); 140 149 continue; 141 150 } … … 144 153 static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr); 145 154 146 if(static_lease_ip) 147 { 148 printf("Found static lease: %x\n", static_lease_ip); 155 if (static_lease_ip) { 156 bb_info_msg("Found static lease: %x", static_lease_ip); 149 157 150 158 memcpy(&static_lease.chaddr, &packet.chaddr, 16); … … 153 161 154 162 lease = &static_lease; 155 156 } 157 else 158 { 159 lease = find_lease_by_chaddr(packet.chaddr); 163 } else { 164 lease = find_lease_by_chaddr(packet.chaddr); 160 165 } 161 166 162 167 switch (state[0]) { 163 168 case DHCPDISCOVER: 164 DEBUG( LOG_INFO,"received DISCOVER");169 DEBUG("Received DISCOVER"); 165 170 166 171 if (sendOffer(&packet) < 0) { 167 LOG(LOG_ERR,"send OFFER failed");172 bb_error_msg("send OFFER failed"); 168 173 } 169 174 break; 170 175 case DHCPREQUEST: 171 DEBUG( LOG_INFO,"received REQUEST");176 DEBUG("received REQUEST"); 172 177 173 178 requested = get_option(&packet, DHCP_REQUESTED_IP); … … 180 185 if (server_id) { 181 186 /* SELECTING State */ 182 DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align)); 183 if (server_id_align == server_config.server && requested && 184 requested_align == lease->yiaddr) { 187 DEBUG("server_id = %08x", ntohl(server_id_align)); 188 if (server_id_align == server_config.server && requested 189 && requested_align == lease->yiaddr 190 ) { 185 191 sendACK(&packet, lease->yiaddr); 186 192 } 193 } else if (requested) { 194 /* INIT-REBOOT State */ 195 if (lease->yiaddr == requested_align) 196 sendACK(&packet, lease->yiaddr); 197 else 198 sendNAK(&packet); 199 } else if (lease->yiaddr == packet.ciaddr) { 200 /* RENEWING or REBINDING State */ 201 sendACK(&packet, lease->yiaddr); 187 202 } else { 188 if (requested) { 189 /* INIT-REBOOT State */ 190 if (lease->yiaddr == requested_align) 191 sendACK(&packet, lease->yiaddr); 192 else sendNAK(&packet); 193 } else { 194 /* RENEWING or REBINDING State */ 195 if (lease->yiaddr == packet.ciaddr) 196 sendACK(&packet, lease->yiaddr); 197 else { 198 /* don't know what to do!!!! */ 199 sendNAK(&packet); 200 } 201 } 203 /* don't know what to do!!!! */ 204 sendNAK(&packet); 202 205 } 203 206 … … 208 211 } else if (requested) { 209 212 /* INIT-REBOOT State */ 210 if ((lease = find_lease_by_yiaddr(requested_align))) { 213 lease = find_lease_by_yiaddr(requested_align); 214 if (lease) { 211 215 if (lease_expired(lease)) { 212 216 /* probably best if we drop this lease */ 213 217 memset(lease->chaddr, 0, 16); 214 218 /* make some contention for this address */ 215 } else sendNAK(&packet); 216 } else if (requested_align < server_config.start || 217 requested_align > server_config.end) { 218 sendNAK(&packet); 219 } /* else remain silent */ 219 } else 220 sendNAK(&packet); 221 } else { 222 uint32_t r = ntohl(requested_align); 223 if (r < server_config.start_ip 224 || r > server_config.end_ip 225 ) { 226 sendNAK(&packet); 227 } 228 /* else remain silent */ 229 } 220 230 221 231 } else { 222 232 /* RENEWING or REBINDING State */ 223 233 } 224 234 break; 225 235 case DHCPDECLINE: 226 DEBUG( LOG_INFO,"received DECLINE");236 DEBUG("Received DECLINE"); 227 237 if (lease) { 228 238 memset(lease->chaddr, 0, 16); … … 231 241 break; 232 242 case DHCPRELEASE: 233 DEBUG(LOG_INFO,"received RELEASE"); 234 if (lease) lease->expires = time(0); 243 DEBUG("Received RELEASE"); 244 if (lease) 245 lease->expires = time(0); 235 246 break; 236 247 case DHCPINFORM: 237 DEBUG( LOG_INFO,"received INFORM");248 DEBUG("Received INFORM"); 238 249 send_inform(&packet); 239 250 break; 240 251 default: 241 LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); 242 } 243 } 244 245 return 0; 252 bb_info_msg("Unsupported DHCP message (%02x) - ignoring", state[0]); 253 } 254 } 255 ret0: 256 retval = 0; 257 ret: 258 /*if (server_config.pidfile) - server_config.pidfile is never NULL */ 259 remove_pidfile(server_config.pidfile); 260 return retval; 246 261 } 247 -
branches/stable/mindi-busybox/networking/udhcp/dhcpd.h
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* dhcpd.h */ 2 3 #ifndef _DHCPD_H 3 4 #define _DHCPD_H 4 5 #include <netinet/ip.h>6 #include <netinet/udp.h>7 8 #include "libbb_udhcp.h"9 #include "leases.h"10 5 11 6 /************************************/ … … 20 15 #define DHCPD_CONF_FILE "/etc/udhcpd.conf" 21 16 22 /*****************************************************************/23 /* Do not modify below here unless you know what you are doing!! */24 /*****************************************************************/25 26 /* DHCP protocol -- see RFC 2131 */27 #define SERVER_PORT 6728 #define CLIENT_PORT 6829 30 #define DHCP_MAGIC 0x6382536331 32 /* DHCP option codes (partial list) */33 #define DHCP_PADDING 0x0034 #define DHCP_SUBNET 0x0135 #define DHCP_TIME_OFFSET 0x0236 #define DHCP_ROUTER 0x0337 #define DHCP_TIME_SERVER 0x0438 #define DHCP_NAME_SERVER 0x0539 #define DHCP_DNS_SERVER 0x0640 #define DHCP_LOG_SERVER 0x0741 #define DHCP_COOKIE_SERVER 0x0842 #define DHCP_LPR_SERVER 0x0943 #define DHCP_HOST_NAME 0x0c44 #define DHCP_BOOT_SIZE 0x0d45 #define DHCP_DOMAIN_NAME 0x0f46 #define DHCP_SWAP_SERVER 0x1047 #define DHCP_ROOT_PATH 0x1148 #define DHCP_IP_TTL 0x1749 #define DHCP_MTU 0x1a50 #define DHCP_BROADCAST 0x1c51 #define DHCP_NTP_SERVER 0x2a52 #define DHCP_WINS_SERVER 0x2c53 #define DHCP_REQUESTED_IP 0x3254 #define DHCP_LEASE_TIME 0x3355 #define DHCP_OPTION_OVER 0x3456 #define DHCP_MESSAGE_TYPE 0x3557 #define DHCP_SERVER_ID 0x3658 #define DHCP_PARAM_REQ 0x3759 #define DHCP_MESSAGE 0x3860 #define DHCP_MAX_SIZE 0x3961 #define DHCP_T1 0x3a62 #define DHCP_T2 0x3b63 #define DHCP_VENDOR 0x3c64 #define DHCP_CLIENT_ID 0x3d65 #define DHCP_FQDN 0x5166 67 #define DHCP_END 0xFF68 69 70 #define BOOTREQUEST 171 #define BOOTREPLY 272 73 #define ETH_10MB 174 #define ETH_10MB_LEN 675 76 #define DHCPDISCOVER 177 #define DHCPOFFER 278 #define DHCPREQUEST 379 #define DHCPDECLINE 480 #define DHCPACK 581 #define DHCPNAK 682 #define DHCPRELEASE 783 #define DHCPINFORM 884 85 #define BROADCAST_FLAG 0x800086 87 #define OPTION_FIELD 088 #define FILE_FIELD 189 #define SNAME_FIELD 290 91 /* miscellaneous defines */92 #define MAC_BCAST_ADDR (uint8_t *) "\xff\xff\xff\xff\xff\xff"93 #define OPT_CODE 094 #define OPT_LEN 195 #define OPT_DATA 296 97 17 struct option_set { 98 18 uint8_t *data; … … 101 21 102 22 struct static_lease { 23 struct static_lease *next; 103 24 uint8_t *mac; 104 25 uint32_t *ip; 105 struct static_lease *next;106 26 }; 107 27 108 28 struct server_config_t { 109 uint32_t server; /* Our IP, in network order */ 110 uint32_t start; /* Start address of leases, network order */ 111 uint32_t end; /* End of leases, network order */ 112 struct option_set *options; /* List of DHCP options loaded from the config file */ 113 char *interface; /* The name of the interface to use */ 114 int ifindex; /* Index number of the interface to use */ 115 uint8_t arp[6]; /* Our arp address */ 116 unsigned long lease; /* lease time in seconds (host order) */ 117 unsigned long max_leases; /* maximum number of leases (including reserved address) */ 118 char remaining; /* should the lease file be interpreted as lease time remaining, or 119 * as the time the lease expires */ 120 unsigned long auto_time; /* how long should udhcpd wait before writing a config file. 121 * if this is zero, it will only write one on SIGUSR1 */ 122 unsigned long decline_time; /* how long an address is reserved if a client returns a 123 * decline message */ 124 unsigned long conflict_time; /* how long an arp conflict offender is leased for */ 125 unsigned long offer_time; /* how long an offered address is reserved */ 126 unsigned long min_lease; /* minimum lease a client can request*/ 29 uint32_t server; /* Our IP, in network order */ 30 /* start,end are in host order: we need to compare start <= ip <= end */ 31 uint32_t start_ip; /* Start address of leases, in host order */ 32 uint32_t end_ip; /* End of leases, in host order */ 33 struct option_set *options; /* List of DHCP options loaded from the config file */ 34 char *interface; /* The name of the interface to use */ 35 int ifindex; /* Index number of the interface to use */ 36 uint8_t arp[6]; /* Our arp address */ 37 char remaining; /* should the lease file be interpreted as lease time remaining, or 38 * as the time the lease expires */ 39 uint32_t lease; /* lease time in seconds (host order) */ 40 uint32_t max_leases; /* maximum number of leases (including reserved address) */ 41 uint32_t auto_time; /* how long should udhcpd wait before writing a config file. 42 * if this is zero, it will only write one on SIGUSR1 */ 43 uint32_t decline_time; /* how long an address is reserved if a client returns a 44 * decline message */ 45 uint32_t conflict_time; /* how long an arp conflict offender is leased for */ 46 uint32_t offer_time; /* how long an offered address is reserved */ 47 uint32_t min_lease; /* minimum lease a client can request */ 127 48 char *lease_file; 128 49 char *pidfile; 129 char *notify_file; 130 uint32_t siaddr; 131 char *sname; 132 char *boot_file; 50 char *notify_file; /* What to run whenever leases are written */ 51 uint32_t siaddr; /* next server bootp option */ 52 char *sname; /* bootp server name */ 53 char *boot_file; /* bootp boot file option */ 133 54 struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */ 134 55 }; … … 138 59 139 60 61 /*** leases.h ***/ 62 63 struct dhcpOfferedAddr { 64 uint8_t chaddr[16]; 65 uint32_t yiaddr; /* network order */ 66 uint32_t expires; /* host order */ 67 }; 68 69 struct dhcpOfferedAddr *add_lease(const uint8_t *chaddr, uint32_t yiaddr, unsigned long lease); 70 int lease_expired(struct dhcpOfferedAddr *lease); 71 struct dhcpOfferedAddr *find_lease_by_chaddr(const uint8_t *chaddr); 72 struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr); 73 uint32_t find_address(int check_expired); 74 75 76 /*** static_leases.h ***/ 77 78 /* Config file will pass static lease info to this function which will add it 79 * to a data structure that can be searched later */ 80 int addStaticLease(struct static_lease **lease_struct, uint8_t *mac, uint32_t *ip); 81 /* Check to see if a mac has an associated static lease */ 82 uint32_t getIpByMac(struct static_lease *lease_struct, void *arg); 83 /* Check to see if an ip is reserved as a static ip */ 84 uint32_t reservedIp(struct static_lease *lease_struct, uint32_t ip); 85 /* Print out static leases just to check what's going on (debug code) */ 86 void printStaticLeases(struct static_lease **lease_struct); 87 88 89 /*** serverpacket.h ***/ 90 91 int sendOffer(struct dhcpMessage *oldpacket); 92 int sendNAK(struct dhcpMessage *oldpacket); 93 int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr); 94 int send_inform(struct dhcpMessage *oldpacket); 95 96 97 /*** files.h ***/ 98 99 int read_config(const char *file); 100 void write_leases(void); 101 void read_leases(const char *file); 102 struct option_set *find_option(struct option_set *opt_list, char code); 103 104 140 105 #endif -
branches/stable/mindi-busybox/networking/udhcp/dumpleases.c
r821 r1770 3 3 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 4 4 */ 5 #include <fcntl.h>6 #include <string.h>7 #include <stdlib.h>8 #include <stdio.h>9 #include <sys/wait.h>10 #include <arpa/inet.h>11 #include <netdb.h>12 #include <netinet/in.h>13 #include <stdio.h>14 #include <sys/socket.h>15 #include <unistd.h>16 5 #include <getopt.h> 17 #include <time.h>18 6 7 #include "common.h" 19 8 #include "dhcpd.h" 20 #include "leases.h"21 #include "libbb_udhcp.h"22 9 23 #define REMAINING 0 24 #define ABSOLUTE 1 25 26 27 #ifndef IN_BUSYBOX 28 static void ATTRIBUTE_NORETURN show_usage(void) 10 int dumpleases_main(int argc, char **argv); 11 int dumpleases_main(int argc, char **argv) 29 12 { 30 printf( 31 "Usage: dumpleases -f <file> -[r|a]\n\n" 32 " -f, --file=FILENAME Leases file to load\n" 33 " -r, --remaining Interepret lease times as time remaining\n" 34 " -a, --absolute Interepret lease times as expire time\n"); 35 exit(0); 36 } 37 #else 38 #define show_usage bb_show_usage 39 #endif 40 41 42 #ifdef IN_BUSYBOX 43 int dumpleases_main(int argc, char *argv[]) 44 #else 45 int main(int argc, char *argv[]) 46 #endif 47 { 48 FILE *fp; 49 int i, c, mode = REMAINING; 50 long expires; 13 int fd; 14 int i; 15 unsigned opt; 16 time_t expires; 51 17 const char *file = LEASES_FILE; 52 18 struct dhcpOfferedAddr lease; 53 19 struct in_addr addr; 54 20 55 static const struct option options[] = { 56 {"absolute", 0, 0, 'a'}, 57 {"remaining", 0, 0, 'r'}, 58 {"file", 1, 0, 'f'}, 59 {0, 0, 0, 0} 21 enum { 22 OPT_a = 0x1, // -a 23 OPT_r = 0x2, // -r 24 OPT_f = 0x4, // -f 60 25 }; 26 #if ENABLE_GETOPT_LONG 27 static const char dumpleases_longopts[] ALIGN1 = 28 "absolute\0" No_argument "a" 29 "remaining\0" No_argument "r" 30 "file\0" Required_argument "f" 31 ; 61 32 62 while (1) {63 int option_index = 0; 64 c = getopt_long(argc, argv, "arf:", options, &option_index);65 if (c == -1) break;33 applet_long_options = dumpleases_longopts; 34 #endif 35 opt_complementary = "=0:a--r:r--a"; 36 opt = getopt32(argv, "arf:", &file); 66 37 67 switch (c) { 68 case 'a': mode = ABSOLUTE; break; 69 case 'r': mode = REMAINING; break; 70 case 'f': 71 file = optarg; 72 break; 73 default: 74 show_usage(); 75 } 76 } 38 fd = xopen(file, O_RDONLY); 77 39 78 fp = xfopen(file, "r"); 79 80 printf("Mac Address IP-Address Expires %s\n", mode == REMAINING ? "in" : "at"); 40 printf("Mac Address IP-Address Expires %s\n", (opt & OPT_a) ? "at" : "in"); 81 41 /* "00:00:00:00:00:00 255.255.255.255 Wed Jun 30 21:49:08 1993" */ 82 while (fread(&lease, sizeof(lease), 1, fp)) { 83 84 for (i = 0; i < 6; i++) { 85 printf("%02x", lease.chaddr[i]); 86 if (i != 5) printf(":"); 42 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) { 43 printf(":%02x"+1, lease.chaddr[0]); 44 for (i = 1; i < 6; i++) { 45 printf(":%02x", lease.chaddr[i]); 87 46 } 88 47 addr.s_addr = lease.yiaddr; 89 printf(" %-15s ", inet_ntoa(addr));48 printf(" %-15s ", inet_ntoa(addr)); 90 49 expires = ntohl(lease.expires); 91 printf(" ");92 if (mode == REMAINING) {93 if (!expires) printf("expired\n");50 if (!(opt & OPT_a)) { /* no -a */ 51 if (!expires) 52 puts("expired"); 94 53 else { 95 if (expires > 60*60*24) { 96 printf("%ld days, ", expires / (60*60*24)); 97 expires %= 60*60*24; 98 } 99 if (expires > 60*60) { 100 printf("%ld hours, ", expires / (60*60)); 101 expires %= 60*60; 102 } 103 if (expires > 60) { 104 printf("%ld minutes, ", expires / 60); 105 expires %= 60; 106 } 107 printf("%ld seconds\n", expires); 54 unsigned d, h, m; 55 d = expires / (24*60*60); expires %= (24*60*60); 56 h = expires / (60*60); expires %= (60*60); 57 m = expires / 60; expires %= 60; 58 if (d) printf("%u days ", d); 59 printf("%02u:%02u:%02u\n", h, m, (unsigned)expires); 108 60 } 109 } else printf("%s", ctime(&expires)); 61 } else /* -a */ 62 fputs(ctime(&expires), stdout); 110 63 } 111 fclose(fp);64 /* close(fd); */ 112 65 113 66 return 0; -
branches/stable/mindi-busybox/networking/udhcp/files.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * files.c -- DHCP server file manipulation * … … 4 5 */ 5 6 6 #include <sys/socket.h>7 #include <arpa/inet.h>8 #include <string.h>9 #include <stdlib.h>10 #include <time.h>11 #include <ctype.h>12 #include <netdb.h>13 14 7 #include <netinet/ether.h> 15 #include "static_leases.h" 16 8 9 #include "common.h" 17 10 #include "dhcpd.h" 18 11 #include "options.h" 19 #include "files.h" 20 #include "common.h" 12 13 14 /* on these functions, make sure your datatype matches */ 15 static int read_ip(const char *line, void *arg) 16 { 17 len_and_sockaddr *lsa; 18 19 lsa = host_and_af2sockaddr(line, 0, AF_INET); 20 if (!lsa) 21 return 0; 22 *(uint32_t*)arg = lsa->sin.sin_addr.s_addr; 23 free(lsa); 24 return 1; 25 } 26 27 static int read_mac(const char *line, void *arg) 28 { 29 uint8_t *mac_bytes = arg; 30 struct ether_addr *temp_ether_addr; 31 32 temp_ether_addr = ether_aton(line); 33 if (temp_ether_addr == NULL) 34 return 0; 35 memcpy(mac_bytes, temp_ether_addr, 6); 36 return 1; 37 } 38 39 40 static int read_str(const char *line, void *arg) 41 { 42 char **dest = arg; 43 44 free(*dest); 45 *dest = xstrdup(line); 46 return 1; 47 } 48 49 50 static int read_u32(const char *line, void *arg) 51 { 52 *(uint32_t*)arg = bb_strtou32(line, NULL, 10); 53 return errno == 0; 54 } 55 56 57 static int read_yn(const char *line, void *arg) 58 { 59 char *dest = arg; 60 61 if (!strcasecmp("yes", line)) { 62 *dest = 1; 63 return 1; 64 } 65 if (!strcasecmp("no", line)) { 66 *dest = 0; 67 return 1; 68 } 69 return 0; 70 } 71 72 73 /* find option 'code' in opt_list */ 74 struct option_set *find_option(struct option_set *opt_list, char code) 75 { 76 while (opt_list && opt_list->data[OPT_CODE] < code) 77 opt_list = opt_list->next; 78 79 if (opt_list && opt_list->data[OPT_CODE] == code) 80 return opt_list; 81 return NULL; 82 } 83 84 85 /* add an option to the opt_list */ 86 static void attach_option(struct option_set **opt_list, 87 const struct dhcp_option *option, char *buffer, int length) 88 { 89 struct option_set *existing, *new, **curr; 90 91 existing = find_option(*opt_list, option->code); 92 if (!existing) { 93 DEBUG("Attaching option %s to list", option->name); 94 95 #if ENABLE_FEATURE_RFC3397 96 if ((option->flags & TYPE_MASK) == OPTION_STR1035) 97 /* reuse buffer and length for RFC1035-formatted string */ 98 buffer = dname_enc(NULL, 0, buffer, &length); 99 #endif 100 101 /* make a new option */ 102 new = xmalloc(sizeof(*new)); 103 new->data = xmalloc(length + 2); 104 new->data[OPT_CODE] = option->code; 105 new->data[OPT_LEN] = length; 106 memcpy(new->data + 2, buffer, length); 107 108 curr = opt_list; 109 while (*curr && (*curr)->data[OPT_CODE] < option->code) 110 curr = &(*curr)->next; 111 112 new->next = *curr; 113 *curr = new; 114 #if ENABLE_FEATURE_RFC3397 115 if ((option->flags & TYPE_MASK) == OPTION_STR1035 && buffer != NULL) 116 free(buffer); 117 #endif 118 return; 119 } 120 121 /* add it to an existing option */ 122 DEBUG("Attaching option %s to existing member of list", option->name); 123 if (option->flags & OPTION_LIST) { 124 #if ENABLE_FEATURE_RFC3397 125 if ((option->flags & TYPE_MASK) == OPTION_STR1035) 126 /* reuse buffer and length for RFC1035-formatted string */ 127 buffer = dname_enc(existing->data + 2, 128 existing->data[OPT_LEN], buffer, &length); 129 #endif 130 if (existing->data[OPT_LEN] + length <= 255) { 131 existing->data = xrealloc(existing->data, 132 existing->data[OPT_LEN] + length + 3); 133 if ((option->flags & TYPE_MASK) == OPTION_STRING) { 134 /* ' ' can bring us to 256 - bad */ 135 if (existing->data[OPT_LEN] + length >= 255) 136 return; 137 /* add space separator between STRING options in a list */ 138 existing->data[existing->data[OPT_LEN] + 2] = ' '; 139 existing->data[OPT_LEN]++; 140 } 141 memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length); 142 existing->data[OPT_LEN] += length; 143 } /* else, ignore the data, we could put this in a second option in the future */ 144 #if ENABLE_FEATURE_RFC3397 145 if ((option->flags & TYPE_MASK) == OPTION_STR1035 && buffer != NULL) 146 free(buffer); 147 #endif 148 } /* else, ignore the new data */ 149 } 150 151 152 /* read a dhcp option and add it to opt_list */ 153 static int read_opt(const char *const_line, void *arg) 154 { 155 struct option_set **opt_list = arg; 156 char *opt, *val, *endptr; 157 const struct dhcp_option *option; 158 int retval = 0, length; 159 char buffer[8]; 160 char *line; 161 uint16_t *result_u16 = (uint16_t *) buffer; 162 uint32_t *result_u32 = (uint32_t *) buffer; 163 164 /* Cheat, the only const line we'll actually get is "" */ 165 line = (char *) const_line; 166 opt = strtok(line, " \t="); 167 if (!opt) return 0; 168 169 option = dhcp_options; 170 while (1) { 171 if (!option->code) 172 return 0; 173 if (!strcasecmp(option->name, opt)) 174 break; 175 option++; 176 } 177 178 do { 179 val = strtok(NULL, ", \t"); 180 if (!val) break; 181 length = option_lengths[option->flags & TYPE_MASK]; 182 retval = 0; 183 opt = buffer; /* new meaning for variable opt */ 184 switch (option->flags & TYPE_MASK) { 185 case OPTION_IP: 186 retval = read_ip(val, buffer); 187 break; 188 case OPTION_IP_PAIR: 189 retval = read_ip(val, buffer); 190 val = strtok(NULL, ", \t/-"); 191 if (!val) 192 retval = 0; 193 if (retval) 194 retval = read_ip(val, buffer + 4); 195 break; 196 case OPTION_STRING: 197 #if ENABLE_FEATURE_RFC3397 198 case OPTION_STR1035: 199 #endif 200 length = strlen(val); 201 if (length > 0) { 202 if (length > 254) length = 254; 203 opt = val; 204 retval = 1; 205 } 206 break; 207 case OPTION_BOOLEAN: 208 retval = read_yn(val, buffer); 209 break; 210 case OPTION_U8: 211 buffer[0] = strtoul(val, &endptr, 0); 212 retval = (endptr[0] == '\0'); 213 break; 214 /* htonX are macros in older libc's, using temp var 215 * in code below for safety */ 216 /* TODO: use bb_strtoX? */ 217 case OPTION_U16: { 218 unsigned long tmp = strtoul(val, &endptr, 0); 219 *result_u16 = htons(tmp); 220 retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/); 221 break; 222 } 223 case OPTION_S16: { 224 long tmp = strtol(val, &endptr, 0); 225 *result_u16 = htons(tmp); 226 retval = (endptr[0] == '\0'); 227 break; 228 } 229 case OPTION_U32: { 230 unsigned long tmp = strtoul(val, &endptr, 0); 231 *result_u32 = htonl(tmp); 232 retval = (endptr[0] == '\0'); 233 break; 234 } 235 case OPTION_S32: { 236 long tmp = strtol(val, &endptr, 0); 237 *result_u32 = htonl(tmp); 238 retval = (endptr[0] == '\0'); 239 break; 240 } 241 default: 242 break; 243 } 244 if (retval) 245 attach_option(opt_list, option, opt, length); 246 } while (retval && option->flags & OPTION_LIST); 247 return retval; 248 } 249 250 static int read_staticlease(const char *const_line, void *arg) 251 { 252 char *line; 253 char *mac_string; 254 char *ip_string; 255 uint8_t *mac_bytes; 256 uint32_t *ip; 257 258 /* Allocate memory for addresses */ 259 mac_bytes = xmalloc(sizeof(unsigned char) * 8); 260 ip = xmalloc(sizeof(uint32_t)); 261 262 /* Read mac */ 263 line = (char *) const_line; 264 mac_string = strtok(line, " \t"); 265 read_mac(mac_string, mac_bytes); 266 267 /* Read ip */ 268 ip_string = strtok(NULL, " \t"); 269 read_ip(ip_string, ip); 270 271 addStaticLease(arg, mac_bytes, ip); 272 273 if (ENABLE_FEATURE_UDHCP_DEBUG) printStaticLeases(arg); 274 275 return 1; 276 } 277 278 279 struct config_keyword { 280 const char *keyword; 281 int (*handler)(const char *line, void *var); 282 void *var; 283 const char *def; 284 }; 285 286 static const struct config_keyword keywords[] = { 287 /* keyword handler variable address default */ 288 {"start", read_ip, &(server_config.start_ip), "192.168.0.20"}, 289 {"end", read_ip, &(server_config.end_ip), "192.168.0.254"}, 290 {"interface", read_str, &(server_config.interface), "eth0"}, 291 {"option", read_opt, &(server_config.options), ""}, 292 {"opt", read_opt, &(server_config.options), ""}, 293 /* Avoid "max_leases value not sane" warning by setting default 294 * to default_end_ip - default_start_ip + 1: */ 295 {"max_leases", read_u32, &(server_config.max_leases), "235"}, 296 {"remaining", read_yn, &(server_config.remaining), "yes"}, 297 {"auto_time", read_u32, &(server_config.auto_time), "7200"}, 298 {"decline_time", read_u32, &(server_config.decline_time), "3600"}, 299 {"conflict_time",read_u32, &(server_config.conflict_time),"3600"}, 300 {"offer_time", read_u32, &(server_config.offer_time), "60"}, 301 {"min_lease", read_u32, &(server_config.min_lease), "60"}, 302 {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, 303 {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"}, 304 {"notify_file", read_str, &(server_config.notify_file), ""}, 305 {"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"}, 306 {"sname", read_str, &(server_config.sname), ""}, 307 {"boot_file", read_str, &(server_config.boot_file), ""}, 308 {"static_lease", read_staticlease, &(server_config.static_leases), ""}, 309 /* ADDME: static lease */ 310 }; 311 21 312 22 313 /* … … 27 318 #define READ_CONFIG_BUF_SIZE 80 28 319 29 /* on these functions, make sure you datatype matches */30 static int read_ip(const char *line, void *arg)31 {32 struct in_addr *addr = arg;33 struct hostent *host;34 int retval = 1;35 36 if (!inet_aton(line, addr)) {37 if ((host = gethostbyname(line)))38 addr->s_addr = *((unsigned long *) host->h_addr_list[0]);39 else retval = 0;40 }41 return retval;42 }43 44 static int read_mac(const char *line, void *arg)45 {46 uint8_t *mac_bytes = arg;47 struct ether_addr *temp_ether_addr;48 int retval = 1;49 50 temp_ether_addr = ether_aton(line);51 52 if(temp_ether_addr == NULL)53 retval = 0;54 else55 memcpy(mac_bytes, temp_ether_addr, 6);56 57 return retval;58 }59 60 61 static int read_str(const char *line, void *arg)62 {63 char **dest = arg;64 65 free(*dest);66 *dest = strdup(line);67 68 return 1;69 }70 71 72 static int read_u32(const char *line, void *arg)73 {74 uint32_t *dest = arg;75 char *endptr;76 *dest = strtoul(line, &endptr, 0);77 return endptr[0] == '\0';78 }79 80 81 static int read_yn(const char *line, void *arg)82 {83 char *dest = arg;84 int retval = 1;85 86 if (!strcasecmp("yes", line))87 *dest = 1;88 else if (!strcasecmp("no", line))89 *dest = 0;90 else retval = 0;91 92 return retval;93 }94 95 96 /* find option 'code' in opt_list */97 struct option_set *find_option(struct option_set *opt_list, char code)98 {99 while (opt_list && opt_list->data[OPT_CODE] < code)100 opt_list = opt_list->next;101 102 if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list;103 else return NULL;104 }105 106 107 /* add an option to the opt_list */108 static void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length)109 {110 struct option_set *existing, *new, **curr;111 112 /* add it to an existing option */113 if ((existing = find_option(*opt_list, option->code))) {114 DEBUG(LOG_INFO, "Attaching option %s to existing member of list", option->name);115 if (option->flags & OPTION_LIST) {116 if (existing->data[OPT_LEN] + length <= 255) {117 existing->data = realloc(existing->data,118 existing->data[OPT_LEN] + length + 2);119 memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length);120 existing->data[OPT_LEN] += length;121 } /* else, ignore the data, we could put this in a second option in the future */122 } /* else, ignore the new data */123 } else {124 DEBUG(LOG_INFO, "Attaching option %s to list", option->name);125 126 /* make a new option */127 new = xmalloc(sizeof(struct option_set));128 new->data = xmalloc(length + 2);129 new->data[OPT_CODE] = option->code;130 new->data[OPT_LEN] = length;131 memcpy(new->data + 2, buffer, length);132 133 curr = opt_list;134 while (*curr && (*curr)->data[OPT_CODE] < option->code)135 curr = &(*curr)->next;136 137 new->next = *curr;138 *curr = new;139 }140 }141 142 143 /* read a dhcp option and add it to opt_list */144 static int read_opt(const char *const_line, void *arg)145 {146 struct option_set **opt_list = arg;147 char *opt, *val, *endptr;148 struct dhcp_option *option;149 int retval = 0, length;150 char buffer[8];151 char *line;152 uint16_t *result_u16 = (uint16_t *) buffer;153 uint32_t *result_u32 = (uint32_t *) buffer;154 155 /* Cheat, the only const line we'll actually get is "" */156 line = (char *) const_line;157 if (!(opt = strtok(line, " \t="))) return 0;158 159 for (option = dhcp_options; option->code; option++)160 if (!strcasecmp(option->name, opt))161 break;162 163 if (!option->code) return 0;164 165 do {166 if (!(val = strtok(NULL, ", \t"))) break;167 length = option_lengths[option->flags & TYPE_MASK];168 retval = 0;169 opt = buffer; /* new meaning for variable opt */170 switch (option->flags & TYPE_MASK) {171 case OPTION_IP:172 retval = read_ip(val, buffer);173 break;174 case OPTION_IP_PAIR:175 retval = read_ip(val, buffer);176 if (!(val = strtok(NULL, ", \t/-"))) retval = 0;177 if (retval) retval = read_ip(val, buffer + 4);178 break;179 case OPTION_STRING:180 length = strlen(val);181 if (length > 0) {182 if (length > 254) length = 254;183 opt = val;184 retval = 1;185 }186 break;187 case OPTION_BOOLEAN:188 retval = read_yn(val, buffer);189 break;190 case OPTION_U8:191 buffer[0] = strtoul(val, &endptr, 0);192 retval = (endptr[0] == '\0');193 break;194 case OPTION_U16:195 *result_u16 = htons(strtoul(val, &endptr, 0));196 retval = (endptr[0] == '\0');197 break;198 case OPTION_S16:199 *result_u16 = htons(strtol(val, &endptr, 0));200 retval = (endptr[0] == '\0');201 break;202 case OPTION_U32:203 *result_u32 = htonl(strtoul(val, &endptr, 0));204 retval = (endptr[0] == '\0');205 break;206 case OPTION_S32:207 *result_u32 = htonl(strtol(val, &endptr, 0));208 retval = (endptr[0] == '\0');209 break;210 default:211 break;212 }213 if (retval)214 attach_option(opt_list, option, opt, length);215 } while (retval && option->flags & OPTION_LIST);216 return retval;217 }218 219 static int read_staticlease(const char *const_line, void *arg)220 {221 222 char *line;223 char *mac_string;224 char *ip_string;225 uint8_t *mac_bytes;226 uint32_t *ip;227 228 229 /* Allocate memory for addresses */230 mac_bytes = xmalloc(sizeof(unsigned char) * 8);231 ip = xmalloc(sizeof(uint32_t));232 233 /* Read mac */234 line = (char *) const_line;235 mac_string = strtok(line, " \t");236 read_mac(mac_string, mac_bytes);237 238 /* Read ip */239 ip_string = strtok(NULL, " \t");240 read_ip(ip_string, ip);241 242 addStaticLease(arg, mac_bytes, ip);243 244 if (ENABLE_FEATURE_UDHCP_DEBUG) printStaticLeases(arg);245 246 return 1;247 248 }249 250 251 static const struct config_keyword keywords[] = {252 /* keyword handler variable address default */253 {"start", read_ip, &(server_config.start), "192.168.0.20"},254 {"end", read_ip, &(server_config.end), "192.168.0.254"},255 {"interface", read_str, &(server_config.interface), "eth0"},256 {"option", read_opt, &(server_config.options), ""},257 {"opt", read_opt, &(server_config.options), ""},258 {"max_leases", read_u32, &(server_config.max_leases), "254"},259 {"remaining", read_yn, &(server_config.remaining), "yes"},260 {"auto_time", read_u32, &(server_config.auto_time), "7200"},261 {"decline_time",read_u32, &(server_config.decline_time),"3600"},262 {"conflict_time",read_u32,&(server_config.conflict_time),"3600"},263 {"offer_time", read_u32, &(server_config.offer_time), "60"},264 {"min_lease", read_u32, &(server_config.min_lease), "60"},265 {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE},266 {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"},267 {"notify_file", read_str, &(server_config.notify_file), ""},268 {"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"},269 {"sname", read_str, &(server_config.sname), ""},270 {"boot_file", read_str, &(server_config.boot_file), ""},271 {"static_lease",read_staticlease, &(server_config.static_leases), ""},272 /*ADDME: static lease */273 {"", NULL, NULL, ""}274 };275 276 277 320 int read_config(const char *file) 278 321 { … … 281 324 int i, lm = 0; 282 325 283 for (i = 0; keywords[i].keyword[0]; i++)326 for (i = 0; i < ARRAY_SIZE(keywords); i++) 284 327 if (keywords[i].def[0]) 285 328 keywords[i].handler(keywords[i].def, keywords[i].var); 286 329 287 i f (!(in = fopen(file, "r"))) {288 LOG(LOG_ERR, "unable to open config file: %s", file);330 in = fopen_or_warn(file, "r"); 331 if (!in) { 289 332 return 0; 290 333 } … … 292 335 while (fgets(buffer, READ_CONFIG_BUF_SIZE, in)) { 293 336 char debug_orig[READ_CONFIG_BUF_SIZE]; 337 char *p; 294 338 295 339 lm++; 296 if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0'; 340 p = strchr(buffer, '\n'); 341 if (p) *p = '\0'; 297 342 if (ENABLE_FEATURE_UDHCP_DEBUG) strcpy(debug_orig, buffer); 298 if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0'; 343 p = strchr(buffer, '#'); 344 if (p) *p = '\0'; 299 345 300 346 if (!(token = strtok(buffer, " \t"))) continue; … … 302 348 303 349 /* eat leading whitespace */ 304 line = line + strspn(line, " \t=");350 line = skip_whitespace(line); 305 351 /* eat trailing whitespace */ 306 for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--); 307 line[i] = '\0'; 308 309 for (i = 0; keywords[i].keyword[0]; i++) 352 i = strlen(line) - 1; 353 while (i >= 0 && isspace(line[i])) 354 line[i--] = '\0'; 355 356 for (i = 0; i < ARRAY_SIZE(keywords); i++) 310 357 if (!strcasecmp(token, keywords[i].keyword)) 311 358 if (!keywords[i].handler(line, keywords[i].var)) { 312 LOG(LOG_ERR, "Failure parsing line %d of %s", lm, file); 313 DEBUG(LOG_ERR, "unable to parse '%s'", debug_orig); 359 bb_error_msg("cannot parse line %d of %s", lm, file); 360 if (ENABLE_FEATURE_UDHCP_DEBUG) 361 bb_error_msg("cannot parse '%s'", debug_orig); 314 362 /* reset back to the default value */ 315 363 keywords[i].handler(keywords[i].def, keywords[i].var); … … 317 365 } 318 366 fclose(in); 367 368 server_config.start_ip = ntohl(server_config.start_ip); 369 server_config.end_ip = ntohl(server_config.end_ip); 370 319 371 return 1; 320 372 } … … 323 375 void write_leases(void) 324 376 { 325 FILE *fp; 326 unsigned int i; 327 char buf[255]; 377 int fp; 378 unsigned i; 328 379 time_t curr = time(0); 329 380 unsigned long tmp_time; 330 381 331 if (!(fp = fopen(server_config.lease_file, "w"))) {332 LOG(LOG_ERR, "Unable to open %s for writing", server_config.lease_file);382 fp = open3_or_warn(server_config.lease_file, O_WRONLY|O_CREAT|O_TRUNC, 0666); 383 if (fp < 0) { 333 384 return; 334 385 } … … 346 397 } /* else stick with the time we got */ 347 398 leases[i].expires = htonl(leases[i].expires); 348 fwrite(&leases[i], sizeof(struct dhcpOfferedAddr), 1, fp); 349 350 /* Then restore it when done. */ 399 // FIXME: error check?? 400 full_write(fp, &leases[i], sizeof(leases[i])); 401 402 /* then restore it when done */ 351 403 leases[i].expires = tmp_time; 352 404 } 353 405 } 354 fclose(fp);406 close(fp); 355 407 356 408 if (server_config.notify_file) { 357 sprintf(buf, "%s %s", server_config.notify_file, server_config.lease_file); 358 system(buf); 409 char *cmd = xasprintf("%s %s", server_config.notify_file, server_config.lease_file); 410 system(cmd); 411 free(cmd); 359 412 } 360 413 } … … 363 416 void read_leases(const char *file) 364 417 { 365 FILE *fp;418 int fp; 366 419 unsigned int i = 0; 367 420 struct dhcpOfferedAddr lease; 368 421 369 if (!(fp = fopen(file, "r"))) {370 LOG(LOG_ERR, "Unable to open %s for reading", file);422 fp = open_or_warn(file, O_RDONLY); 423 if (fp < 0) { 371 424 return; 372 425 } 373 426 374 while (i < server_config.max_leases && (fread(&lease, sizeof lease, 1, fp) == 1)) { 427 while (i < server_config.max_leases 428 && full_read(fp, &lease, sizeof(lease)) == sizeof(lease) 429 ) { 375 430 /* ADDME: is it a static lease */ 376 if (lease.yiaddr >= server_config.start && lease.yiaddr <= server_config.end) { 431 uint32_t y = ntohl(lease.yiaddr); 432 if (y >= server_config.start_ip && y <= server_config.end_ip) { 377 433 lease.expires = ntohl(lease.expires); 378 if (!server_config.remaining) lease.expires -= time(0); 434 if (!server_config.remaining) 435 lease.expires -= time(0); 379 436 if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) { 380 LOG(LOG_WARNING, "Too many leases while loading %s\n", file);437 bb_error_msg("too many leases while loading %s", file); 381 438 break; 382 439 } … … 384 441 } 385 442 } 386 DEBUG( LOG_INFO,"Read %d leases", i);387 fclose(fp);388 } 443 DEBUG("Read %d leases", i); 444 close(fp); 445 } -
branches/stable/mindi-busybox/networking/udhcp/leases.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * leases.c -- tools to manage DHCP leases … … 4 5 */ 5 6 6 #include <time.h> 7 #include <string.h> 8 #include <sys/socket.h> 9 #include <netinet/in.h> 10 #include <arpa/inet.h> 11 7 #include "common.h" 12 8 #include "dhcpd.h" 13 #include "files.h"14 #include "options.h"15 #include "leases.h"16 #include "arpping.h"17 #include "common.h"18 19 #include "static_leases.h"20 9 21 10 22 uint8_t blank_chaddr[] = {[0 ... 15] = 0}; 11 /* Find the oldest expired lease, NULL if there are no expired leases */ 12 static struct dhcpOfferedAddr *oldest_expired_lease(void) 13 { 14 struct dhcpOfferedAddr *oldest = NULL; 15 // TODO: use monotonic_sec() 16 unsigned long oldest_lease = time(0); 17 unsigned i; 18 19 for (i = 0; i < server_config.max_leases; i++) 20 if (oldest_lease > leases[i].expires) { 21 oldest_lease = leases[i].expires; 22 oldest = &(leases[i]); 23 } 24 return oldest; 25 } 26 23 27 24 28 /* clear every lease out that chaddr OR yiaddr matches and is nonzero */ 25 void clear_lease(uint8_t *chaddr, uint32_t yiaddr)29 static void clear_lease(const uint8_t *chaddr, uint32_t yiaddr) 26 30 { 27 unsigned i nt i, j;31 unsigned i, j; 28 32 29 for (j = 0; j < 16 && !chaddr[j]; j++); 33 for (j = 0; j < 16 && !chaddr[j]; j++) 34 continue; 30 35 31 36 for (i = 0; i < server_config.max_leases; i++) 32 if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) || 33 (yiaddr && leases[i].yiaddr == yiaddr)) { 34 memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr)); 37 if ((j != 16 && memcmp(leases[i].chaddr, chaddr, 16) == 0) 38 || (yiaddr && leases[i].yiaddr == yiaddr) 39 ) { 40 memset(&(leases[i]), 0, sizeof(leases[i])); 35 41 } 36 42 } … … 38 44 39 45 /* add a lease into the table, clearing out any old ones */ 40 struct dhcpOfferedAddr *add_lease( uint8_t *chaddr, uint32_t yiaddr, unsigned long lease)46 struct dhcpOfferedAddr *add_lease(const uint8_t *chaddr, uint32_t yiaddr, unsigned long lease) 41 47 { 42 48 struct dhcpOfferedAddr *oldest; … … 64 70 65 71 66 /* Find the oldest expired lease, NULL if there are no expired leases*/67 struct dhcpOfferedAddr * oldest_expired_lease(void)72 /* Find the first lease that matches chaddr, NULL if no match */ 73 struct dhcpOfferedAddr *find_lease_by_chaddr(const uint8_t *chaddr) 68 74 { 69 struct dhcpOfferedAddr *oldest = NULL; 70 unsigned long oldest_lease = time(0); 71 unsigned int i; 72 75 unsigned i; 73 76 74 77 for (i = 0; i < server_config.max_leases; i++) 75 if (oldest_lease > leases[i].expires) { 76 oldest_lease = leases[i].expires; 77 oldest = &(leases[i]); 78 } 79 return oldest; 80 81 } 82 83 84 /* Find the first lease that matches chaddr, NULL if no match */ 85 struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr) 86 { 87 unsigned int i; 88 89 for (i = 0; i < server_config.max_leases; i++) 90 if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]); 78 if (!memcmp(leases[i].chaddr, chaddr, 16)) 79 return &(leases[i]); 91 80 92 81 return NULL; … … 97 86 struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr) 98 87 { 99 unsigned i nt i;88 unsigned i; 100 89 101 90 for (i = 0; i < server_config.max_leases; i++) 102 if (leases[i].yiaddr == yiaddr) return &(leases[i]); 91 if (leases[i].yiaddr == yiaddr) 92 return &(leases[i]); 103 93 104 94 return NULL; … … 107 97 108 98 /* check is an IP is taken, if it is, add it to the lease table */ 109 static int check_ip(uint32_t addr)99 static int nobody_responds_to_arp(uint32_t addr) 110 100 { 101 static const uint8_t blank_chaddr[16]; /* 16 zero bytes */ 102 111 103 struct in_addr temp; 104 int r; 112 105 113 if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { 114 temp.s_addr = addr; 115 LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds", 116 inet_ntoa(temp), server_config.conflict_time); 117 add_lease(blank_chaddr, addr, server_config.conflict_time); 118 return 1; 119 } else return 0; 106 r = arpping(addr, server_config.server, server_config.arp, server_config.interface); 107 if (r) 108 return r; 109 110 temp.s_addr = addr; 111 bb_info_msg("%s belongs to someone, reserving it for %u seconds", 112 inet_ntoa(temp), (unsigned)server_config.conflict_time); 113 add_lease(blank_chaddr, addr, server_config.conflict_time); 114 return 0; 120 115 } 121 116 122 117 123 /* find an assignable address, i tcheck_expired is true, we check all the expired leases as well.118 /* find an assignable address, if check_expired is true, we check all the expired leases as well. 124 119 * Maybe this should try expired leases by age... */ 125 120 uint32_t find_address(int check_expired) … … 128 123 struct dhcpOfferedAddr *lease = NULL; 129 124 130 addr = ntohl(server_config.start); /* addr is in host order here */ 131 for (;addr <= ntohl(server_config.end); addr++) { 132 125 addr = server_config.start_ip; /* addr is in host order here */ 126 for (; addr <= server_config.end_ip; addr++) { 133 127 /* ie, 192.168.55.0 */ 134 if (!(addr & 0xFF)) continue;135 128 if (!(addr & 0xFF)) 129 continue; 136 130 /* ie, 192.168.55.255 */ 137 if ((addr & 0xFF) == 0xFF) continue; 138 139 /* Only do if it isn't an assigned as a static lease */ 140 if(!reservedIp(server_config.static_leases, htonl(addr))) 141 { 142 143 /* lease is not taken */ 131 if ((addr & 0xFF) == 0xFF) 132 continue; 133 /* Only do if it isn't assigned as a static lease */ 144 134 ret = htonl(addr); 145 if ( (!(lease = find_lease_by_yiaddr(ret)) ||146 147 /* or it expired and we are checking for expired leases */148 (check_expired && lease_expired(lease))) &&149 150 /* and it isn'ton the network */151 !check_ip(ret)) {152 return ret;153 break;135 if (!reservedIp(server_config.static_leases, ret)) { 136 /* lease is not taken */ 137 lease = find_lease_by_yiaddr(ret); 138 /* no lease or it expired and we are checking for expired leases */ 139 if ((!lease || (check_expired && lease_expired(lease))) 140 && nobody_responds_to_arp(ret) /* it isn't used on the network */ 141 ) { 142 return ret; 143 } 154 144 } 155 }156 145 } 157 146 return 0; -
branches/stable/mindi-busybox/networking/udhcp/options.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * options.c -- DHCP server option packet tools … … 4 5 */ 5 6 6 #include <stdlib.h>7 #include <string.h>8 9 7 #include "common.h" 10 8 #include "dhcpd.h" 11 9 #include "options.h" 12 #include "files.h"13 10 14 11 15 12 /* supported options are easily added here */ 16 struct dhcp_option dhcp_options[] = { 17 /* name[10] flags code */ 18 {"subnet", OPTION_IP | OPTION_REQ, 0x01}, 19 {"timezone", OPTION_S32, 0x02}, 20 {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, 21 {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, 22 {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, 23 {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, 24 {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, 25 {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, 26 {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, 27 {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, 28 {"bootsize", OPTION_U16, 0x0d}, 29 {"domain", OPTION_STRING | OPTION_REQ, 0x0f}, 30 {"swapsvr", OPTION_IP, 0x10}, 31 {"rootpath", OPTION_STRING, 0x11}, 32 {"ipttl", OPTION_U8, 0x17}, 33 {"mtu", OPTION_U16, 0x1a}, 34 {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, 35 {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, 36 {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, 37 {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, 38 {"wins", OPTION_IP | OPTION_LIST, 0x2c}, 39 {"requestip", OPTION_IP, 0x32}, 40 {"lease", OPTION_U32, 0x33}, 41 {"dhcptype", OPTION_U8, 0x35}, 42 {"serverid", OPTION_IP, 0x36}, 43 {"message", OPTION_STRING, 0x38}, 44 {"tftp", OPTION_STRING, 0x42}, 45 {"bootfile", OPTION_STRING, 0x43}, 46 {"", 0x00, 0x00} 13 const struct dhcp_option dhcp_options[] = { 14 /* name[12] flags code */ 15 {"subnet", OPTION_IP | OPTION_REQ, 0x01}, 16 {"timezone", OPTION_S32, 0x02}, 17 {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, 18 {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, 19 {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, 20 {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, 21 {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, 22 {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, 23 {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, 24 {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, 25 {"bootsize", OPTION_U16, 0x0d}, 26 {"domain", OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f}, 27 {"swapsvr", OPTION_IP, 0x10}, 28 {"rootpath", OPTION_STRING, 0x11}, 29 {"ipttl", OPTION_U8, 0x17}, 30 {"mtu", OPTION_U16, 0x1a}, 31 {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, 32 {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, 33 {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, 34 {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, 35 {"wins", OPTION_IP | OPTION_LIST, 0x2c}, 36 {"requestip", OPTION_IP, 0x32}, 37 {"lease", OPTION_U32, 0x33}, 38 {"dhcptype", OPTION_U8, 0x35}, 39 {"serverid", OPTION_IP, 0x36}, 40 {"message", OPTION_STRING, 0x38}, 41 {"vendorclass", OPTION_STRING, 0x3C}, 42 {"clientid", OPTION_STRING, 0x3D}, 43 {"tftp", OPTION_STRING, 0x42}, 44 {"bootfile", OPTION_STRING, 0x43}, 45 {"userclass", OPTION_STRING, 0x4D}, 46 #if ENABLE_FEATURE_RFC3397 47 {"search", OPTION_STR1035 | OPTION_LIST | OPTION_REQ, 0x77}, 48 #endif 49 /* MSIE's "Web Proxy Autodiscovery Protocol" support */ 50 {"wpad", OPTION_STRING, 0xfc}, 51 {"", 0x00, 0x00} 47 52 }; 48 53 49 54 /* Lengths of the different option types */ 50 int option_lengths[] = { 51 [OPTION_IP] = 4, 52 [OPTION_IP_PAIR] = 8, 53 [OPTION_BOOLEAN] = 1, 54 [OPTION_STRING] = 1, 55 [OPTION_U8] = 1, 56 [OPTION_U16] = 2, 57 [OPTION_S16] = 2, 58 [OPTION_U32] = 4, 59 [OPTION_S32] = 4 55 const unsigned char option_lengths[] ALIGN1 = { 56 [OPTION_IP] = 4, 57 [OPTION_IP_PAIR] = 8, 58 [OPTION_BOOLEAN] = 1, 59 [OPTION_STRING] = 1, 60 #if ENABLE_FEATURE_RFC3397 61 [OPTION_STR1035] = 1, 62 #endif 63 [OPTION_U8] = 1, 64 [OPTION_U16] = 2, 65 [OPTION_S16] = 2, 66 [OPTION_U32] = 4, 67 [OPTION_S32] = 4 60 68 }; 61 69 … … 73 81 while (!done) { 74 82 if (i >= length) { 75 LOG(LOG_WARNING, "bogus packet, option fields too long.");83 bb_error_msg("bogus packet, option fields too long"); 76 84 return NULL; 77 85 } 78 86 if (optionptr[i + OPT_CODE] == code) { 79 87 if (i + 1 + optionptr[i + OPT_LEN] >= length) { 80 LOG(LOG_WARNING, "bogus packet, option fields too long.");88 bb_error_msg("bogus packet, option fields too long"); 81 89 return NULL; 82 90 } … … 89 97 case DHCP_OPTION_OVER: 90 98 if (i + 1 + optionptr[i + OPT_LEN] >= length) { 91 LOG(LOG_WARNING, "bogus packet, option fields too long.");99 bb_error_msg("bogus packet, option fields too long"); 92 100 return NULL; 93 101 } … … 137 145 /* end position + string length + option code/length + end option */ 138 146 if (end + string[OPT_LEN] + 2 + 1 >= 308) { 139 LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", string[OPT_CODE]); 147 bb_error_msg("option 0x%02x did not fit into the packet", 148 string[OPT_CODE]); 140 149 return 0; 141 150 } 142 DEBUG( LOG_INFO,"adding option 0x%02x", string[OPT_CODE]);151 DEBUG("adding option 0x%02x", string[OPT_CODE]); 143 152 memcpy(optionptr + end, string, string[OPT_LEN] + 2); 144 153 optionptr[end + string[OPT_LEN] + 2] = DHCP_END; … … 150 159 int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) 151 160 { 152 struct dhcp_option *dh;161 const struct dhcp_option *dh; 153 162 154 for (dh =dhcp_options; dh->code; dh++) {163 for (dh = dhcp_options; dh->code; dh++) { 155 164 if (dh->code == code) { 156 165 uint8_t option[6], len; … … 167 176 } 168 177 169 DEBUG(LOG_ERR, "Couldnot add option 0x%02x", code);178 bb_error_msg("cannot add option 0x%02x", code); 170 179 return 0; 171 180 } -
branches/stable/mindi-busybox/networking/udhcp/options.h
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* options.h */ 2 3 #ifndef _OPTIONS_H 3 4 #define _OPTIONS_H 4 5 #include "packet.h"6 5 7 6 #define TYPE_MASK 0x0F … … 11 10 OPTION_IP_PAIR, 12 11 OPTION_STRING, 12 #if ENABLE_FEATURE_RFC3397 13 OPTION_STR1035, /* RFC1035 compressed domain name list */ 14 #endif 13 15 OPTION_BOOLEAN, 14 16 OPTION_U8, … … 22 24 #define OPTION_LIST 0x20 /* There can be a list of 1 or more of these */ 23 25 26 /*****************************************************************/ 27 /* Do not modify below here unless you know what you are doing!! */ 28 /*****************************************************************/ 29 30 /* DHCP protocol -- see RFC 2131 */ 31 #define SERVER_PORT 67 32 #define CLIENT_PORT 68 33 34 #define DHCP_MAGIC 0x63825363 35 36 /* DHCP option codes (partial list) */ 37 #define DHCP_PADDING 0x00 38 #define DHCP_SUBNET 0x01 39 #define DHCP_TIME_OFFSET 0x02 40 #define DHCP_ROUTER 0x03 41 #define DHCP_TIME_SERVER 0x04 42 #define DHCP_NAME_SERVER 0x05 43 #define DHCP_DNS_SERVER 0x06 44 #define DHCP_LOG_SERVER 0x07 45 #define DHCP_COOKIE_SERVER 0x08 46 #define DHCP_LPR_SERVER 0x09 47 #define DHCP_HOST_NAME 0x0c 48 #define DHCP_BOOT_SIZE 0x0d 49 #define DHCP_DOMAIN_NAME 0x0f 50 #define DHCP_SWAP_SERVER 0x10 51 #define DHCP_ROOT_PATH 0x11 52 #define DHCP_IP_TTL 0x17 53 #define DHCP_MTU 0x1a 54 #define DHCP_BROADCAST 0x1c 55 #define DHCP_NTP_SERVER 0x2a 56 #define DHCP_WINS_SERVER 0x2c 57 #define DHCP_REQUESTED_IP 0x32 58 #define DHCP_LEASE_TIME 0x33 59 #define DHCP_OPTION_OVER 0x34 60 #define DHCP_MESSAGE_TYPE 0x35 61 #define DHCP_SERVER_ID 0x36 62 #define DHCP_PARAM_REQ 0x37 63 #define DHCP_MESSAGE 0x38 64 #define DHCP_MAX_SIZE 0x39 65 #define DHCP_T1 0x3a 66 #define DHCP_T2 0x3b 67 #define DHCP_VENDOR 0x3c 68 #define DHCP_CLIENT_ID 0x3d 69 #define DHCP_FQDN 0x51 70 71 #define DHCP_END 0xFF 72 73 74 #define BOOTREQUEST 1 75 #define BOOTREPLY 2 76 77 #define ETH_10MB 1 78 #define ETH_10MB_LEN 6 79 80 #define DHCPDISCOVER 1 81 #define DHCPOFFER 2 82 #define DHCPREQUEST 3 83 #define DHCPDECLINE 4 84 #define DHCPACK 5 85 #define DHCPNAK 6 86 #define DHCPRELEASE 7 87 #define DHCPINFORM 8 88 89 #define BROADCAST_FLAG 0x8000 90 91 #define OPTION_FIELD 0 92 #define FILE_FIELD 1 93 #define SNAME_FIELD 2 94 95 /* miscellaneous defines */ 96 #define OPT_CODE 0 97 #define OPT_LEN 1 98 #define OPT_DATA 2 99 24 100 struct dhcp_option { 25 char name[1 0];101 char name[12]; 26 102 char flags; 27 103 uint8_t code; 28 104 }; 29 105 30 extern struct dhcp_option dhcp_options[];31 extern intoption_lengths[];106 extern const struct dhcp_option dhcp_options[]; 107 extern const unsigned char option_lengths[]; 32 108 33 109 uint8_t *get_option(struct dhcpMessage *packet, int code); … … 35 111 int add_option_string(uint8_t *optionptr, uint8_t *string); 36 112 int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data); 113 #if ENABLE_FEATURE_RFC3397 114 char *dname_dec(const uint8_t *cstr, int clen, const char *pre); 115 uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen); 116 #endif 37 117 38 118 #endif -
branches/stable/mindi-busybox/networking/udhcp/packet.c
r821 r1770 1 #include <unistd.h> 2 #include <string.h> 1 /* vi: set sw=4 ts=4: */ 2 3 3 #include <netinet/in.h> 4 #include <sys/types.h> 5 #include <sys/socket.h> 6 #include <features.h> 7 #if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION 4 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION 8 5 #include <netpacket/packet.h> 9 6 #include <net/ethernet.h> … … 13 10 #include <linux/if_ether.h> 14 11 #endif 15 #include <errno.h>16 12 17 13 #include "common.h" 18 #include "packet.h"19 14 #include "dhcpd.h" 20 15 #include "options.h" … … 47 42 int udhcp_get_packet(struct dhcpMessage *packet, int fd) 48 43 { 44 #if 0 49 45 static const char broken_vendors[][8] = { 50 46 "MSFT 98", 51 47 "" 52 48 }; 49 #endif 53 50 int bytes; 54 int i; 55 char unsigned *vendor; 56 57 memset(packet, 0, sizeof(struct dhcpMessage)); 58 bytes = read(fd, packet, sizeof(struct dhcpMessage)); 51 unsigned char *vendor; 52 53 memset(packet, 0, sizeof(*packet)); 54 bytes = read(fd, packet, sizeof(*packet)); 59 55 if (bytes < 0) { 60 DEBUG( LOG_INFO, "couldn't read on listening socket, ignoring");56 DEBUG("cannot read on listening socket, ignoring"); 61 57 return -1; 62 58 } 63 59 64 60 if (ntohl(packet->cookie) != DHCP_MAGIC) { 65 LOG(LOG_ERR,"received bogus message, ignoring");61 bb_error_msg("received bogus message, ignoring"); 66 62 return -2; 67 63 } 68 DEBUG(LOG_INFO, "Received a packet"); 69 70 if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) { 71 for (i = 0; broken_vendors[i][0]; i++) { 72 if (vendor[OPT_LEN - 2] == (uint8_t) strlen(broken_vendors[i]) && 73 !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])) { 74 DEBUG(LOG_INFO, "broken client (%s), forcing broadcast", 75 broken_vendors[i]); 64 DEBUG("Received a packet"); 65 66 if (packet->op == BOOTREQUEST) { 67 vendor = get_option(packet, DHCP_VENDOR); 68 if (vendor) { 69 #if 0 70 int i; 71 for (i = 0; broken_vendors[i][0]; i++) { 72 if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i]) 73 && !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2]) 74 ) { 75 DEBUG("broken client (%s), forcing broadcast", 76 broken_vendors[i]); 77 packet->flags |= htons(BROADCAST_FLAG); 78 } 79 } 80 #else 81 if (vendor[OPT_LEN - 2] == (uint8_t)(sizeof("MSFT 98")-1) 82 && memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0 83 ) { 84 DEBUG("broken client (%s), forcing broadcast", "MSFT 98"); 76 85 packet->flags |= htons(BROADCAST_FLAG); 77 86 } 87 #endif 78 88 } 79 89 } … … 88 98 * beginning at location "addr". 89 99 */ 90 registerint32_t sum = 0;100 int32_t sum = 0; 91 101 uint16_t *source = (uint16_t *) addr; 92 102 … … 114 124 115 125 /* Construct a ip/udp header for a packet, and specify the source and dest hardware address */ 116 int udhcp_raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, 117 uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex) 126 void BUG_sizeof_struct_udp_dhcp_packet_must_be_576(void); 127 int udhcp_raw_packet(struct dhcpMessage *payload, 128 uint32_t source_ip, int source_port, 129 uint32_t dest_ip, int dest_port, const uint8_t *dest_arp, int ifindex) 118 130 { 119 131 int fd; … … 122 134 struct udp_dhcp_packet packet; 123 135 124 if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { 125 DEBUG(LOG_ERR, "socket call failed: %m"); 136 fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 137 if (fd < 0) { 138 bb_perror_msg("socket"); 126 139 return -1; 127 140 } … … 136 149 memcpy(dest.sll_addr, dest_arp, 6); 137 150 if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) { 138 DEBUG(LOG_ERR, "bind call failed: %m");151 bb_perror_msg("bind"); 139 152 close(fd); 140 153 return -1; … … 157 170 packet.ip.check = udhcp_checksum(&(packet.ip), sizeof(packet.ip)); 158 171 159 result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest)); 172 if (sizeof(struct udp_dhcp_packet) != 576) 173 BUG_sizeof_struct_udp_dhcp_packet_must_be_576(); 174 175 result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, 176 (struct sockaddr *) &dest, sizeof(dest)); 160 177 if (result <= 0) { 161 DEBUG(LOG_ERR, "write on socket failed: %m");178 bb_perror_msg("sendto"); 162 179 } 163 180 close(fd); … … 167 184 168 185 /* Let the kernel do all the work for packet generation */ 169 int udhcp_kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,170 uint32_t dest_ip, int dest_port)171 { 172 int n = 1; 186 int udhcp_kernel_packet(struct dhcpMessage *payload, 187 uint32_t source_ip, int source_port, 188 uint32_t dest_ip, int dest_port) 189 { 173 190 int fd, result; 174 191 struct sockaddr_in client; 175 192 176 if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 177 return -1; 178 179 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) { 180 close(fd); 181 return -1; 182 } 193 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 194 if (fd < 0) 195 return -1; 196 197 setsockopt_reuseaddr(fd); 183 198 184 199 memset(&client, 0, sizeof(client)); … … 187 202 client.sin_addr.s_addr = source_ip; 188 203 189 if (bind(fd, (struct sockaddr *)&client, sizeof( struct sockaddr)) == -1) {204 if (bind(fd, (struct sockaddr *)&client, sizeof(client)) == -1) { 190 205 close(fd); 191 206 return -1; -
branches/stable/mindi-busybox/networking/udhcp/script.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* script.c 2 3 * … … 8 9 */ 9 10 10 #include <string.h>11 #include <unistd.h>12 #include <stdio.h>13 #include <stdlib.h>14 #include <sys/socket.h>15 #include <netinet/in.h>16 #include <arpa/inet.h>17 #include <sys/types.h>18 #include <sys/wait.h>19 20 11 #include "common.h" 12 #include "dhcpc.h" 21 13 #include "options.h" 22 #include "dhcpd.h" 23 #include "dhcpc.h" 14 24 15 25 16 /* get a rough idea of how long an option will be (rounding up...) */ 26 static const int max_option_length[] = {17 static const uint8_t max_option_length[] = { 27 18 [OPTION_IP] = sizeof("255.255.255.255 "), 28 19 [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, 29 20 [OPTION_STRING] = 1, 21 #if ENABLE_FEATURE_RFC3397 22 [OPTION_STR1035] = 1, 23 #endif 30 24 [OPTION_BOOLEAN] = sizeof("yes "), 31 25 [OPTION_U8] = sizeof("255 "), … … 44 38 45 39 46 static int sprintip(char *dest, c har *pre,uint8_t *ip)40 static int sprintip(char *dest, const char *pre, const uint8_t *ip) 47 41 { 48 42 return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]); … … 62 56 63 57 64 /* Fill destwith the text of option 'option'. */65 static void fill_options(char *dest, uint8_t *option,struct dhcp_option *type_p)66 { 67 int type, optlen;58 /* Allocate and fill with the text of option 'option'. */ 59 static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p) 60 { 61 int len, type, optlen; 68 62 uint16_t val_u16; 69 63 int16_t val_s16; 70 64 uint32_t val_u32; 71 65 int32_t val_s32; 72 int len = option[OPT_LEN - 2]; 73 74 dest += sprintf(dest, "%s=", type_p->name); 75 66 char *dest, *ret; 67 68 len = option[OPT_LEN - 2]; 76 69 type = type_p->flags & TYPE_MASK; 77 70 optlen = option_lengths[type]; 78 for(;;) { 71 72 dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->name) + 2); 73 dest += sprintf(ret, "%s=", type_p->name); 74 75 for (;;) { 79 76 switch (type) { 80 77 case OPTION_IP_PAIR: 81 78 dest += sprintip(dest, "", option); 82 * (dest++)= '/';79 *dest++ = '/'; 83 80 option += 4; 84 81 optlen = 4; … … 111 108 memcpy(dest, option, len); 112 109 dest[len] = '\0'; 113 return; /* Short circuit this case */ 110 return ret; /* Short circuit this case */ 111 #if ENABLE_FEATURE_RFC3397 112 case OPTION_STR1035: 113 /* unpack option into dest; use ret for prefix (i.e., "optname=") */ 114 dest = dname_dec(option, len, ret); 115 free(ret); 116 return dest; 117 #endif 114 118 } 115 119 option += optlen; … … 118 122 dest += sprintf(dest, " "); 119 123 } 124 return ret; 120 125 } 121 126 … … 127 132 int i, j; 128 133 char **envp; 134 char *var; 129 135 uint8_t *temp; 130 136 struct in_addr subnet; 131 137 char over = 0; 132 138 133 if (packet == NULL) 134 num_options = 0; 135 else { 136 for (i = 0; dhcp_options[i].code; i++) 139 if (packet) { 140 for (i = 0; dhcp_options[i].code; i++) { 137 141 if (get_option(packet, dhcp_options[i].code)) { 138 142 num_options++; … … 140 144 num_options++; /* for mton */ 141 145 } 142 if (packet->siaddr) num_options++; 143 if ((temp = get_option(packet, DHCP_OPTION_OVER))) 146 } 147 if (packet->siaddr) 148 num_options++; 149 temp = get_option(packet, DHCP_OPTION_OVER); 150 if (temp) 144 151 over = *temp; 145 if (!(over & FILE_FIELD) && packet->file[0]) num_options++; 146 if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++; 152 if (!(over & FILE_FIELD) && packet->file[0]) 153 num_options++; 154 if (!(over & SNAME_FIELD) && packet->sname[0]) 155 num_options++; 147 156 } 148 157 149 158 envp = xzalloc(sizeof(char *) * (num_options + 5)); 150 159 j = 0; 151 envp[j++] = bb_xasprintf("interface=%s", client_config.interface); 152 envp[j++] = bb_xasprintf("PATH=%s", 153 getenv("PATH") ? : "/bin:/usr/bin:/sbin:/usr/sbin"); 154 envp[j++] = bb_xasprintf("HOME=%s", getenv("HOME") ? : "/"); 155 156 if (packet == NULL) return envp; 160 envp[j++] = xasprintf("interface=%s", client_config.interface); 161 var = getenv("PATH"); 162 if (var) 163 envp[j++] = xasprintf("PATH=%s", var); 164 var = getenv("HOME"); 165 if (var) 166 envp[j++] = xasprintf("HOME=%s", var); 167 168 if (packet == NULL) 169 return envp; 157 170 158 171 envp[j] = xmalloc(sizeof("ip=255.255.255.255")); 159 172 sprintip(envp[j++], "ip=", (uint8_t *) &packet->yiaddr); 160 173 161 162 174 for (i = 0; dhcp_options[i].code; i++) { 163 if (!(temp = get_option(packet, dhcp_options[i].code))) 175 temp = get_option(packet, dhcp_options[i].code); 176 if (!temp) 164 177 continue; 165 envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], 166 dhcp_options[i].flags & TYPE_MASK) + strlen(dhcp_options[i].name) + 2); 167 fill_options(envp[j++], temp, &dhcp_options[i]); 178 envp[j++] = alloc_fill_opts(temp, &dhcp_options[i]); 168 179 169 180 /* Fill in a subnet bits option for things like /24 */ 170 181 if (dhcp_options[i].code == DHCP_SUBNET) { 171 182 memcpy(&subnet, temp, 4); 172 envp[j++] = bb_xasprintf("mask=%d", mton(&subnet));183 envp[j++] = xasprintf("mask=%d", mton(&subnet)); 173 184 } 174 185 } … … 180 191 /* watch out for invalid packets */ 181 192 packet->file[sizeof(packet->file) - 1] = '\0'; 182 envp[j++] = bb_xasprintf("boot_file=%s", packet->file);193 envp[j++] = xasprintf("boot_file=%s", packet->file); 183 194 } 184 195 if (!(over & SNAME_FIELD) && packet->sname[0]) { 185 196 /* watch out for invalid packets */ 186 197 packet->sname[sizeof(packet->sname) - 1] = '\0'; 187 envp[j++] = bb_xasprintf("sname=%s", packet->sname);198 envp[j++] = xasprintf("sname=%s", packet->sname); 188 199 } 189 200 return envp; … … 200 211 return; 201 212 202 DEBUG( LOG_INFO, "vforking and execle'ing %s", client_config.script);213 DEBUG("vfork'ing and execle'ing %s", client_config.script); 203 214 204 215 envp = fill_envp(packet); 216 205 217 /* call script */ 218 // can we use wait4pid(spawn(...)) here? 206 219 pid = vfork(); 207 if (pid) { 208 waitpid(pid, NULL, 0); 209 for (curr = envp; *curr; curr++) free(*curr); 210 free(envp); 211 return; 212 } else if (pid == 0) { 220 if (pid < 0) return; 221 if (pid == 0) { 213 222 /* close fd's? */ 214 215 223 /* exec script */ 216 224 execle(client_config.script, client_config.script, 217 225 name, NULL, envp); 218 LOG(LOG_ERR, "script %s failed: %m", client_config.script); 219 exit(1); 220 } 221 } 226 bb_perror_msg_and_die("script %s failed", client_config.script); 227 } 228 waitpid(pid, NULL, 0); 229 for (curr = envp; *curr; curr++) 230 free(*curr); 231 free(envp); 232 } -
branches/stable/mindi-busybox/networking/udhcp/serverpacket.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* serverpacket.c 2 3 * … … 20 21 */ 21 22 22 #include <sys/socket.h>23 #include <netinet/in.h>24 #include <arpa/inet.h>25 #include <string.h>26 #include <time.h>27 28 23 #include "common.h" 29 #include "serverpacket.h"30 24 #include "dhcpd.h" 31 25 #include "options.h" 32 #include "static_leases.h" 26 33 27 34 28 /* send a packet to giaddr using the kernel ip stack */ 35 29 static int send_packet_to_relay(struct dhcpMessage *payload) 36 30 { 37 DEBUG( LOG_INFO,"Forwarding packet to relay");31 DEBUG("Forwarding packet to relay"); 38 32 39 33 return udhcp_kernel_packet(payload, server_config.server, SERVER_PORT, … … 45 39 static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcast) 46 40 { 47 uint8_t *chaddr;41 const uint8_t *chaddr; 48 42 uint32_t ciaddr; 49 43 50 44 if (force_broadcast) { 51 DEBUG( LOG_INFO,"broadcasting packet to client (NAK)");45 DEBUG("broadcasting packet to client (NAK)"); 52 46 ciaddr = INADDR_BROADCAST; 53 47 chaddr = MAC_BCAST_ADDR; 54 48 } else if (payload->ciaddr) { 55 DEBUG( LOG_INFO,"unicasting packet to client ciaddr");49 DEBUG("unicasting packet to client ciaddr"); 56 50 ciaddr = payload->ciaddr; 57 51 chaddr = payload->chaddr; 58 52 } else if (ntohs(payload->flags) & BROADCAST_FLAG) { 59 DEBUG( LOG_INFO,"broadcasting packet to client (requested)");53 DEBUG("broadcasting packet to client (requested)"); 60 54 ciaddr = INADDR_BROADCAST; 61 55 chaddr = MAC_BCAST_ADDR; 62 56 } else { 63 DEBUG( LOG_INFO,"unicasting packet to client yiaddr");57 DEBUG("unicasting packet to client yiaddr"); 64 58 ciaddr = payload->yiaddr; 65 59 chaddr = payload->chaddr; … … 122 116 123 117 /* ADDME: if static, short circuit */ 124 if(!static_lease_ip) 125 { 126 /* the client is in our lease/offered table */ 127 if ((lease = find_lease_by_chaddr(oldpacket->chaddr))) { 128 if (!lease_expired(lease)) 129 lease_time_align = lease->expires - time(0); 130 packet.yiaddr = lease->yiaddr; 131 132 /* Or the client has a requested ip */ 133 } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) && 134 135 /* Don't look here (ugly hackish thing to do) */ 136 memcpy(&req_align, req, 4) && 137 138 /* and the ip is in the lease range */ 139 ntohl(req_align) >= ntohl(server_config.start) && 140 ntohl(req_align) <= ntohl(server_config.end) && 141 142 !static_lease_ip && /* Check that its not a static lease */ 143 /* and is not already taken/offered */ 144 ((!(lease = find_lease_by_yiaddr(req_align)) || 145 146 /* or its taken, but expired */ /* ADDME: or maybe in here */ 147 lease_expired(lease)))) { 148 packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */ 149 118 if (!static_lease_ip) { 119 /* the client is in our lease/offered table */ 120 lease = find_lease_by_chaddr(oldpacket->chaddr); 121 if (lease) { 122 if (!lease_expired(lease)) 123 lease_time_align = lease->expires - time(0); 124 packet.yiaddr = lease->yiaddr; 125 /* Or the client has a requested ip */ 126 } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) 127 /* Don't look here (ugly hackish thing to do) */ 128 && memcpy(&req_align, req, 4) 129 /* and the ip is in the lease range */ 130 && ntohl(req_align) >= server_config.start_ip 131 && ntohl(req_align) <= server_config.end_ip 132 && !static_lease_ip /* Check that its not a static lease */ 133 /* and is not already taken/offered */ 134 && (!(lease = find_lease_by_yiaddr(req_align)) 135 /* or its taken, but expired */ /* ADDME: or maybe in here */ 136 || lease_expired(lease)) 137 ) { 138 packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */ 150 139 /* otherwise, find a free IP */ 140 } else { 141 /* Is it a static lease? (No, because find_address skips static lease) */ 142 packet.yiaddr = find_address(0); 143 /* try for an expired lease */ 144 if (!packet.yiaddr) 145 packet.yiaddr = find_address(1); 146 } 147 148 if (!packet.yiaddr) { 149 bb_error_msg("no IP addresses to give - OFFER abandoned"); 150 return -1; 151 } 152 if (!add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time)) { 153 bb_error_msg("lease pool is full - OFFER abandoned"); 154 return -1; 155 } 156 lease_time = get_option(oldpacket, DHCP_LEASE_TIME); 157 if (lease_time) { 158 memcpy(&lease_time_align, lease_time, 4); 159 lease_time_align = ntohl(lease_time_align); 160 if (lease_time_align > server_config.lease) 161 lease_time_align = server_config.lease; 162 } 163 164 /* Make sure we aren't just using the lease time from the previous offer */ 165 if (lease_time_align < server_config.min_lease) 166 lease_time_align = server_config.lease; 167 /* ADDME: end of short circuit */ 151 168 } else { 152 /* Is it a static lease? (No, because find_address skips static lease) */153 packet.yiaddr = find_address(0);154 155 /* try for an expired lease */156 if (!packet.yiaddr) packet.yiaddr = find_address(1);157 }158 159 if(!packet.yiaddr) {160 LOG(LOG_WARNING, "no IP addresses to give -- OFFER abandoned");161 return -1;162 }163 164 if (!add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time)) {165 LOG(LOG_WARNING, "lease pool is full -- OFFER abandoned");166 return -1;167 }168 169 if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) {170 memcpy(&lease_time_align, lease_time, 4);171 lease_time_align = ntohl(lease_time_align);172 if (lease_time_align > server_config.lease)173 lease_time_align = server_config.lease;174 }175 176 /* Make sure we aren't just using the lease time from the previous offer */177 if (lease_time_align < server_config.min_lease)178 lease_time_align = server_config.lease;179 }180 /* ADDME: end of short circuit */181 else182 {183 169 /* It is a static lease... use it */ 184 170 packet.yiaddr = static_lease_ip; … … 197 183 198 184 addr.s_addr = packet.yiaddr; 199 LOG(LOG_INFO, "sending OFFER of %s", inet_ntoa(addr));185 bb_info_msg("Sending OFFER of %s", inet_ntoa(addr)); 200 186 return send_packet(&packet, 0); 201 187 } … … 208 194 init_packet(&packet, oldpacket, DHCPNAK); 209 195 210 DEBUG( LOG_INFO, "sending NAK");196 DEBUG("Sending NAK"); 211 197 return send_packet(&packet, 1); 212 198 } … … 224 210 packet.yiaddr = yiaddr; 225 211 226 if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { 212 lease_time = get_option(oldpacket, DHCP_LEASE_TIME); 213 if (lease_time) { 227 214 memcpy(&lease_time_align, lease_time, 4); 228 215 lease_time_align = ntohl(lease_time_align); … … 245 232 246 233 addr.s_addr = packet.yiaddr; 247 LOG(LOG_INFO, "sending ACK to %s", inet_ntoa(addr));234 bb_info_msg("Sending ACK to %s", inet_ntoa(addr)); 248 235 249 236 if (send_packet(&packet, 0) < 0) … … 251 238 252 239 add_lease(packet.chaddr, packet.yiaddr, lease_time_align); 240 if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) { 241 /* rewrite the file with leases at every new acceptance */ 242 write_leases(); 243 } 253 244 254 245 return 0; -
branches/stable/mindi-busybox/networking/udhcp/signalpipe.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* signalpipe.c 2 3 * … … 20 21 */ 21 22 22 #include <unistd.h> 23 #include <fcntl.h> 24 #include <signal.h> 25 #include <sys/types.h> 26 #include <sys/socket.h> 27 #include <sys/select.h> 23 #include "common.h" 28 24 29 30 #include "signalpipe.h"31 #include "common.h"32 25 33 26 static int signal_pipe[2]; … … 35 28 static void signal_handler(int sig) 36 29 { 37 if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) 38 DEBUG(LOG_ERR, "Could not send signal: %m"); 30 unsigned char ch = sig; /* use char, avoid dealing with partial writes */ 31 if (write(signal_pipe[1], &ch, 1) != 1) 32 bb_perror_msg("cannot send signal"); 39 33 } 40 34 … … 44 38 void udhcp_sp_setup(void) 45 39 { 46 socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe); 40 /* was socketpair, but it needs AF_UNIX in kernel */ 41 xpipe(signal_pipe); 47 42 fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC); 48 43 fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC); 44 fcntl(signal_pipe[1], F_SETFL, O_NONBLOCK); 49 45 signal(SIGUSR1, signal_handler); 50 46 signal(SIGUSR2, signal_handler); … … 73 69 int udhcp_sp_read(fd_set *rfds) 74 70 { 75 intsig;71 unsigned char sig; 76 72 77 73 if (!FD_ISSET(signal_pipe[0], rfds)) 78 74 return 0; 79 75 80 if (read(signal_pipe[0], &sig, sizeof(sig)) < 0)76 if (read(signal_pipe[0], &sig, 1) != 1) 81 77 return -1; 82 78 -
branches/stable/mindi-busybox/networking/udhcp/socket.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * socket.c -- DHCP server client/server socket creation … … 23 24 */ 24 25 25 #include <sys/types.h>26 #include <sys/socket.h>27 #include <sys/ioctl.h>28 #include <netinet/in.h>29 #include <unistd.h>30 #include <string.h>31 #include <arpa/inet.h>32 26 #include <net/if.h> 33 #include <errno.h>34 27 #include <features.h> 35 #if ( __GLIBC__ >= 2 && __GLIBC_MINOR>= 1) || defined _NEWLIB_VERSION28 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION 36 29 #include <netpacket/packet.h> 37 30 #include <net/ethernet.h> … … 43 36 44 37 #include "common.h" 45 #include "socket.h"46 38 47 int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp) 39 40 int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp) 48 41 { 49 42 int fd; … … 51 44 struct sockaddr_in *our_ip; 52 45 53 memset(&ifr, 0, sizeof(struct ifreq)); 54 if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) { 55 ifr.ifr_addr.sa_family = AF_INET; 56 strcpy(ifr.ifr_name, interface); 46 memset(&ifr, 0, sizeof(ifr)); 47 fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 57 48 58 if (addr) { 59 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { 60 our_ip = (struct sockaddr_in *) &ifr.ifr_addr; 61 *addr = our_ip->sin_addr.s_addr; 62 DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr)); 63 } else { 64 LOG(LOG_ERR, "SIOCGIFADDR failed, is the interface up and configured?: %m"); 65 close(fd); 66 return -1; 67 } 68 } 69 70 if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { 71 DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex); 72 *ifindex = ifr.ifr_ifindex; 73 } else { 74 LOG(LOG_ERR, "SIOCGIFINDEX failed!: %m"); 49 ifr.ifr_addr.sa_family = AF_INET; 50 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); 51 if (addr) { 52 if (ioctl_or_perror(fd, SIOCGIFADDR, &ifr, 53 "is interface %s up and configured?", interface) 54 ) { 75 55 close(fd); 76 56 return -1; 77 57 } 78 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) { 79 memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); 80 DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", 81 arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); 82 } else { 83 LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %m"); 58 our_ip = (struct sockaddr_in *) &ifr.ifr_addr; 59 *addr = our_ip->sin_addr.s_addr; 60 DEBUG("%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr)); 61 } 62 63 if (ifindex) { 64 if (ioctl_or_warn(fd, SIOCGIFINDEX, &ifr) != 0) { 84 65 close(fd); 85 66 return -1; 86 67 } 87 } else { 88 LOG(LOG_ERR, "socket failed!: %m"); 89 return -1; 68 DEBUG("adapter index %d", ifr.ifr_ifindex); 69 *ifindex = ifr.ifr_ifindex; 90 70 } 71 72 if (arp) { 73 if (ioctl_or_warn(fd, SIOCGIFHWADDR, &ifr) != 0) { 74 close(fd); 75 return -1; 76 } 77 memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); 78 DEBUG("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", 79 arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); 80 } 81 91 82 close(fd); 92 83 return 0; 93 84 } 94 85 86 /* 1. None of the callers expects it to ever fail */ 87 /* 2. ip was always INADDR_ANY */ 88 int listen_socket(/*uint32_t ip,*/ int port, const char *inf) 89 { 90 int fd; 91 struct ifreq interface; 92 struct sockaddr_in addr; 95 93 96 int listen_socket(uint32_t ip, int port, char *inf) 97 { 98 struct ifreq interface; 99 int fd; 100 struct sockaddr_in addr; 101 int n = 1; 94 DEBUG("Opening listen socket on *:%d %s", port, inf); 95 fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 102 96 103 DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s", ip, port, inf); 104 if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 105 DEBUG(LOG_ERR, "socket call failed: %m"); 106 return -1; 107 } 97 setsockopt_reuseaddr(fd); 98 if (setsockopt_broadcast(fd) == -1) 99 bb_perror_msg_and_die("SO_BROADCAST"); 100 101 strncpy(interface.ifr_name, inf, IFNAMSIZ); 102 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, sizeof(interface)) == -1) 103 bb_perror_msg_and_die("SO_BINDTODEVICE"); 108 104 109 105 memset(&addr, 0, sizeof(addr)); 110 106 addr.sin_family = AF_INET; 111 107 addr.sin_port = htons(port); 112 addr.sin_addr.s_addr = ip; 113 114 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) { 115 close(fd); 116 return -1; 117 } 118 if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) { 119 close(fd); 120 return -1; 121 } 122 123 strncpy(interface.ifr_name, inf, IFNAMSIZ); 124 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) { 125 close(fd); 126 return -1; 127 } 128 129 if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) { 130 close(fd); 131 return -1; 132 } 108 /* addr.sin_addr.s_addr = ip; - all-zeros is INADDR_ANY */ 109 xbind(fd, (struct sockaddr *)&addr, sizeof(addr)); 133 110 134 111 return fd; -
branches/stable/mindi-busybox/networking/udhcp/static_leases.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * static_leases.c -- Couple of functions to assist with storing and … … 7 8 */ 8 9 10 #include "common.h" 11 #include "dhcpd.h" 9 12 10 #include <stdlib.h>11 #include <stdio.h>12 #include <string.h>13 14 #include "static_leases.h"15 #include "dhcpd.h"16 13 17 14 /* Takes the address of the pointer to the static_leases linked list, … … 20 17 int addStaticLease(struct static_lease **lease_struct, uint8_t *mac, uint32_t *ip) 21 18 { 22 23 19 struct static_lease *cur; 24 20 struct static_lease *new_static_lease; … … 31 27 32 28 /* If it's the first node to be added... */ 33 if(*lease_struct == NULL) 34 { 29 if (*lease_struct == NULL) { 35 30 *lease_struct = new_static_lease; 36 } 37 else 38 { 31 } else { 39 32 cur = *lease_struct; 40 while(cur->next != NULL) 41 { 33 while (cur->next) { 42 34 cur = cur->next; 43 35 } … … 47 39 48 40 return 1; 49 50 41 } 51 42 … … 59 50 return_ip = 0; 60 51 61 while(cur != NULL) 62 { 52 while (cur) { 63 53 /* If the client has the correct mac */ 64 if(memcmp(cur->mac, mac, 6) == 0) 65 { 54 if (memcmp(cur->mac, mac, 6) == 0) { 66 55 return_ip = *(cur->ip); 67 56 } … … 71 60 72 61 return return_ip; 73 74 62 } 75 63 … … 81 69 uint32_t return_val = 0; 82 70 83 while(cur != NULL) 84 { 71 while (cur) { 85 72 /* If the client has the correct ip */ 86 if (*cur->ip == ip)73 if (*cur->ip == ip) 87 74 return_val = 1; 88 75 … … 91 78 92 79 return return_val; 93 94 80 } 95 81 96 #if def CONFIG_FEATURE_UDHCP_DEBUG82 #if ENABLE_FEATURE_UDHCP_DEBUG 97 83 /* Print out static leases just to check what's going on */ 98 84 /* Takes the address of the pointer to the static_leases linked list */ … … 102 88 struct static_lease *cur = *arg; 103 89 104 while(cur != NULL) 105 { 90 while (cur) { 106 91 /* printf("PrintStaticLeases: Lease mac Address: %x\n", cur->mac); */ 107 92 printf("PrintStaticLeases: Lease mac Value: %x\n", *(cur->mac)); … … 111 96 cur = cur->next; 112 97 } 113 114 115 98 } 116 99 #endif 117 118 119
Note:
See TracChangeset
for help on using the changeset viewer.