Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/networking/udhcp/dhcpd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 10  Line 10 
10   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11   */   */
12    
13    #include <syslog.h>
14  #include "common.h"  #include "common.h"
15    #include "dhcpc.h"
16  #include "dhcpd.h"  #include "dhcpd.h"
17  #include "options.h"  #include "options.h"
18    
19    
20  /* globals */  /* globals */
21  struct dhcpOfferedAddr *leases;  struct dhcpOfferedAddr *leases;
22  struct server_config_t server_config;  /* struct server_config_t server_config is in bb_common_bufsiz1 */
23    
24    
25  int udhcpd_main(int argc, char *argv[])  int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
26    int udhcpd_main(int argc UNUSED_PARAM, char **argv)
27  {  {
28   fd_set rfds;   fd_set rfds;
29   struct timeval tv;   struct timeval tv;
# Line 28  int udhcpd_main(int argc, char *argv[]) Line 31  int udhcpd_main(int argc, char *argv[])
31   struct dhcpMessage packet;   struct dhcpMessage packet;
32   uint8_t *state, *server_id, *requested;   uint8_t *state, *server_id, *requested;
33   uint32_t server_id_align, requested_align, static_lease_ip;   uint32_t server_id_align, requested_align, static_lease_ip;
34   unsigned long timeout_end, num_ips;   unsigned timeout_end;
35     unsigned num_ips;
36     unsigned opt;
37   struct option_set *option;   struct option_set *option;
38   struct dhcpOfferedAddr *lease, static_lease;   struct dhcpOfferedAddr *lease, static_lease;
39     USE_FEATURE_UDHCP_PORT(char *str_P;)
40    
41   read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);  #if ENABLE_FEATURE_UDHCP_PORT
42     SERVER_PORT = 67;
43   /* Start the log, sanitize fd's, and write a pid file */   CLIENT_PORT = 68;
44   udhcp_start_log_and_pid(server_config.pidfile);  #endif
45    
46     opt = getopt32(argv, "fS" USE_FEATURE_UDHCP_PORT("P:", &str_P));
47     argv += optind;
48    
49     if (!(opt & 1)) { /* no -f */
50     bb_daemonize_or_rexec(0, argv);
51     logmode &= ~LOGMODE_STDIO;
52     }
53    
54   if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) {   if (opt & 2) { /* -S */
55     openlog(applet_name, LOG_PID, LOG_LOCAL0);
56     logmode |= LOGMODE_SYSLOG;
57     }
58    #if ENABLE_FEATURE_UDHCP_PORT
59     if (opt & 4) { /* -P */
60     SERVER_PORT = xatou16(str_P);
61     CLIENT_PORT = SERVER_PORT + 1;
62     }
63    #endif
64     /* Would rather not do read_config before daemonization -
65     * otherwise NOMMU machines will parse config twice */
66     read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
67    
68     /* Make sure fd 0,1,2 are open */
69     bb_sanitize_stdio();
70     /* Equivalent of doing a fflush after every \n */
71     setlinebuf(stdout);
72    
73     /* Create pidfile */
74     write_pidfile(server_config.pidfile);
75     /* if (!..) bb_perror_msg("cannot create pidfile %s", pidfile); */
76    
77     bb_info_msg("%s (v"BB_VER") started", applet_name);
78    
79     option = find_option(server_config.options, DHCP_LEASE_TIME);
80     server_config.lease = LEASE_TIME;
81     if (option) {
82   memcpy(&server_config.lease, option->data + 2, 4);   memcpy(&server_config.lease, option->data + 2, 4);
83   server_config.lease = ntohl(server_config.lease);   server_config.lease = ntohl(server_config.lease);
84   }   }
  else server_config.lease = LEASE_TIME;  
85    
86   /* Sanity check */   /* Sanity check */
87   num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1;   num_ips = server_config.end_ip - server_config.start_ip + 1;
88   if (server_config.max_leases > num_ips) {   if (server_config.max_leases > num_ips) {
89   bb_error_msg("max_leases value (%lu) not sane, "   bb_error_msg("max_leases=%u is too big, setting to %u",
90   "setting to %lu instead",   (unsigned)server_config.max_leases, num_ips);
  server_config.max_leases, num_ips);  
91   server_config.max_leases = num_ips;   server_config.max_leases = num_ips;
92   }   }
93    
94   leases = xzalloc(server_config.max_leases * sizeof(struct dhcpOfferedAddr));   leases = xzalloc(server_config.max_leases * sizeof(*leases));
95   read_leases(server_config.lease_file);   read_leases(server_config.lease_file);
96    
97   if (read_interface(server_config.interface, &server_config.ifindex,   if (udhcp_read_interface(server_config.interface, &server_config.ifindex,
98     &server_config.server, server_config.arp) < 0)     &server_config.server, server_config.arp)) {
99   return 1;   retval = 1;
100     goto ret;
101   if (!ENABLE_FEATURE_UDHCP_DEBUG)   }
  udhcp_background(server_config.pidfile); /* hold lock during fork. */  
102    
103   /* Setup the signal pipe */   /* Setup the signal pipe */
104   udhcp_sp_setup();   udhcp_sp_setup();
105    
106   timeout_end = time(0) + server_config.auto_time;   timeout_end = monotonic_sec() + server_config.auto_time;
107   while (1) { /* loop until universe collapses */   while (1) { /* loop until universe collapses */
108    
109   if (server_socket < 0) {   if (server_socket < 0) {
110   server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface);   server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT,
111     server_config.interface);
112   }   }
113    
114   max_sock = udhcp_sp_fd_set(&rfds, server_socket);   max_sock = udhcp_sp_fd_set(&rfds, server_socket);
115   if (server_config.auto_time) {   if (server_config.auto_time) {
116   tv.tv_sec = timeout_end - time(0);   tv.tv_sec = timeout_end - monotonic_sec();
117   tv.tv_usec = 0;   tv.tv_usec = 0;
118   }   }
119     retval = 0;
120   if (!server_config.auto_time || tv.tv_sec > 0) {   if (!server_config.auto_time || tv.tv_sec > 0) {
121   retval = select(max_sock + 1, &rfds, NULL, NULL,   retval = select(max_sock + 1, &rfds, NULL, NULL,
122   server_config.auto_time ? &tv : NULL);   server_config.auto_time ? &tv : NULL);
123   } else retval = 0; /* If we already timed out, fall through */   }
   
124   if (retval == 0) {   if (retval == 0) {
125   write_leases();   write_leases();
126   timeout_end = time(0) + server_config.auto_time;   timeout_end = monotonic_sec() + server_config.auto_time;
127   continue;   continue;
128   } else if (retval < 0 && errno != EINTR) {   }
129     if (retval < 0 && errno != EINTR) {
130   DEBUG("error on select");   DEBUG("error on select");
131   continue;   continue;
132   }   }
# Line 96  int udhcpd_main(int argc, char *argv[]) Line 136  int udhcpd_main(int argc, char *argv[])
136   bb_info_msg("Received a SIGUSR1");   bb_info_msg("Received a SIGUSR1");
137   write_leases();   write_leases();
138   /* why not just reset the timeout, eh */   /* why not just reset the timeout, eh */
139   timeout_end = time(0) + server_config.auto_time;   timeout_end = monotonic_sec() + server_config.auto_time;
140   continue;   continue;
141   case SIGTERM:   case SIGTERM:
142   bb_info_msg("Received a SIGTERM");   bb_info_msg("Received a SIGTERM");
143   return 0;   goto ret0;
144   case 0: break; /* no signal */   case 0: break; /* no signal */
145   default: continue; /* signal or error (probably EINTR) */   default: continue; /* signal or error (probably EINTR) */
146   }   }
147    
148   if ((bytes = udhcp_get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */   bytes = udhcp_recv_kernel_packet(&packet, server_socket); /* this waits for a packet - idle */
149     if (bytes < 0) {
150   if (bytes == -1 && errno != EINTR) {   if (bytes == -1 && errno != EINTR) {
151   DEBUG("error on read, %s, reopening socket", strerror(errno));   DEBUG("error on read, %s, reopening socket", strerror(errno));
152   close(server_socket);   close(server_socket);
# Line 114  int udhcpd_main(int argc, char *argv[]) Line 155  int udhcpd_main(int argc, char *argv[])
155   continue;   continue;
156   }   }
157    
158   if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {   state = get_option(&packet, DHCP_MESSAGE_TYPE);
159     if (state == NULL) {
160   bb_error_msg("cannot get option from packet, ignoring");   bb_error_msg("cannot get option from packet, ignoring");
161   continue;   continue;
162   }   }
# Line 130  int udhcpd_main(int argc, char *argv[]) Line 172  int udhcpd_main(int argc, char *argv[])
172   static_lease.expires = 0;   static_lease.expires = 0;
173    
174   lease = &static_lease;   lease = &static_lease;
   
175   } else {   } else {
176   lease = find_lease_by_chaddr(packet.chaddr);   lease = find_lease_by_chaddr(packet.chaddr);
177   }   }
# Line 139  int udhcpd_main(int argc, char *argv[]) Line 180  int udhcpd_main(int argc, char *argv[])
180   case DHCPDISCOVER:   case DHCPDISCOVER:
181   DEBUG("Received DISCOVER");   DEBUG("Received DISCOVER");
182    
183   if (sendOffer(&packet) < 0) {   if (send_offer(&packet) < 0) {
184   bb_error_msg("send OFFER failed");   bb_error_msg("send OFFER failed");
185   }   }
186   break;   break;
# Line 156  int udhcpd_main(int argc, char *argv[]) Line 197  int udhcpd_main(int argc, char *argv[])
197   if (server_id) {   if (server_id) {
198   /* SELECTING State */   /* SELECTING State */
199   DEBUG("server_id = %08x", ntohl(server_id_align));   DEBUG("server_id = %08x", ntohl(server_id_align));
200   if (server_id_align == server_config.server && requested &&   if (server_id_align == server_config.server && requested
201      requested_align == lease->yiaddr) {   && requested_align == lease->yiaddr
202   sendACK(&packet, lease->yiaddr);   ) {
203   }   send_ACK(&packet, lease->yiaddr);
  } else {  
  if (requested) {  
  /* INIT-REBOOT State */  
  if (lease->yiaddr == requested_align)  
  sendACK(&packet, lease->yiaddr);  
  else sendNAK(&packet);  
  } else {  
  /* RENEWING or REBINDING State */  
  if (lease->yiaddr == packet.ciaddr)  
  sendACK(&packet, lease->yiaddr);  
  else {  
  /* don't know what to do!!!! */  
  sendNAK(&packet);  
  }  
204   }   }
205     } else if (requested) {
206     /* INIT-REBOOT State */
207     if (lease->yiaddr == requested_align)
208     send_ACK(&packet, lease->yiaddr);
209     else
210     send_NAK(&packet);
211     } else if (lease->yiaddr == packet.ciaddr) {
212     /* RENEWING or REBINDING State */
213     send_ACK(&packet, lease->yiaddr);
214     } else { /* don't know what to do!!!! */
215     send_NAK(&packet);
216   }   }
217    
218   /* what to do if we have no record of the client */   /* what to do if we have no record of the client */
# Line 183  int udhcpd_main(int argc, char *argv[]) Line 221  int udhcpd_main(int argc, char *argv[])
221    
222   } else if (requested) {   } else if (requested) {
223   /* INIT-REBOOT State */   /* INIT-REBOOT State */
224   if ((lease = find_lease_by_yiaddr(requested_align))) {   lease = find_lease_by_yiaddr(requested_align);
225     if (lease) {
226   if (lease_expired(lease)) {   if (lease_expired(lease)) {
227   /* probably best if we drop this lease */   /* probably best if we drop this lease */
228   memset(lease->chaddr, 0, 16);   memset(lease->chaddr, 0, 16);
229   /* make some contention for this address */   /* make some contention for this address */
230   } else sendNAK(&packet);   } else
231   } else if (requested_align < server_config.start ||   send_NAK(&packet);
232     requested_align > server_config.end) {   } else {
233   sendNAK(&packet);   uint32_t r = ntohl(requested_align);
234   } /* else remain silent */   if (r < server_config.start_ip
235             || r > server_config.end_ip
236     ) {
237     send_NAK(&packet);
238     }
239     /* else remain silent */
240     }
241    
242   } else {   } else {
243   /* RENEWING or REBINDING State */   /* RENEWING or REBINDING State */
244   }   }
245   break;   break;
246   case DHCPDECLINE:   case DHCPDECLINE:
# Line 207  int udhcpd_main(int argc, char *argv[]) Line 252  int udhcpd_main(int argc, char *argv[])
252   break;   break;
253   case DHCPRELEASE:   case DHCPRELEASE:
254   DEBUG("Received RELEASE");   DEBUG("Received RELEASE");
255   if (lease) lease->expires = time(0);   if (lease)
256     lease->expires = time(0);
257   break;   break;
258   case DHCPINFORM:   case DHCPINFORM:
259   DEBUG("Received INFORM");   DEBUG("Received INFORM");
# Line 217  int udhcpd_main(int argc, char *argv[]) Line 263  int udhcpd_main(int argc, char *argv[])
263   bb_info_msg("Unsupported DHCP message (%02x) - ignoring", state[0]);   bb_info_msg("Unsupported DHCP message (%02x) - ignoring", state[0]);
264   }   }
265   }   }
266     ret0:
267   return 0;   retval = 0;
268     ret:
269     /*if (server_config.pidfile) - server_config.pidfile is never NULL */
270     remove_pidfile(server_config.pidfile);
271     return retval;
272  }  }

Legend:
Removed from v.815  
changed lines
  Added in v.816