Magellan Linux

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

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

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 18  Line 18 
18    
19    
20  /* globals */  /* globals */
21  struct dhcpOfferedAddr *leases;  struct dyn_lease *g_leases;
22  /* struct server_config_t server_config is in bb_common_bufsiz1 */  /* struct server_config_t server_config is in bb_common_bufsiz1 */
23    
24    
# Line 26  int udhcpd_main(int argc, char **argv) M Line 26  int udhcpd_main(int argc, char **argv) M
26  int udhcpd_main(int argc UNUSED_PARAM, char **argv)  int udhcpd_main(int argc UNUSED_PARAM, char **argv)
27  {  {
28   fd_set rfds;   fd_set rfds;
29   struct timeval tv;   int server_socket = -1, retval, max_sock;
30   int server_socket = -1, bytes, retval, max_sock;   struct dhcp_packet packet;
31   struct dhcpMessage packet;   uint8_t *state;
32   uint8_t *state, *server_id, *requested;   uint32_t static_lease_ip;
  uint32_t server_id_align, requested_align, static_lease_ip;  
33   unsigned timeout_end;   unsigned timeout_end;
34   unsigned num_ips;   unsigned num_ips;
35   unsigned opt;   unsigned opt;
36   struct option_set *option;   struct option_set *option;
37   struct dhcpOfferedAddr *lease, static_lease;   struct dyn_lease *lease, fake_lease;
38   USE_FEATURE_UDHCP_PORT(char *str_P;)   IF_FEATURE_UDHCP_PORT(char *str_P;)
39    
40  #if ENABLE_FEATURE_UDHCP_PORT  #if ENABLE_FEATURE_UDHCP_PORT
41   SERVER_PORT = 67;   SERVER_PORT = 67;
42   CLIENT_PORT = 68;   CLIENT_PORT = 68;
43  #endif  #endif
44    
45   opt = getopt32(argv, "fS" USE_FEATURE_UDHCP_PORT("P:", &str_P));  #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
46     opt_complementary = "vv";
47    #endif
48     opt = getopt32(argv, "fSv"
49     IF_FEATURE_UDHCP_PORT("P:", &str_P)
50    #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
51     , &dhcp_verbose
52    #endif
53     );
54   argv += optind;   argv += optind;
   
55   if (!(opt & 1)) { /* no -f */   if (!(opt & 1)) { /* no -f */
56   bb_daemonize_or_rexec(0, argv);   bb_daemonize_or_rexec(0, argv);
57   logmode &= ~LOGMODE_STDIO;   logmode = LOGMODE_NONE;
58   }   }
   
59   if (opt & 2) { /* -S */   if (opt & 2) { /* -S */
60   openlog(applet_name, LOG_PID, LOG_LOCAL0);   openlog(applet_name, LOG_PID, LOG_DAEMON);
61   logmode |= LOGMODE_SYSLOG;   logmode |= LOGMODE_SYSLOG;
62   }   }
63  #if ENABLE_FEATURE_UDHCP_PORT  #if ENABLE_FEATURE_UDHCP_PORT
64   if (opt & 4) { /* -P */   if (opt & 8) { /* -P */
65   SERVER_PORT = xatou16(str_P);   SERVER_PORT = xatou16(str_P);
66   CLIENT_PORT = SERVER_PORT + 1;   CLIENT_PORT = SERVER_PORT + 1;
67   }   }
# Line 72  int udhcpd_main(int argc UNUSED_PARAM, c Line 77  int udhcpd_main(int argc UNUSED_PARAM, c
77    
78   /* Create pidfile */   /* Create pidfile */
79   write_pidfile(server_config.pidfile);   write_pidfile(server_config.pidfile);
80   /* if (!..) bb_perror_msg("cannot create pidfile %s", pidfile); */   /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
81    
82   bb_info_msg("%s (v"BB_VER") started", applet_name);   bb_info_msg("%s (v"BB_VER") started", applet_name);
83    
84   option = find_option(server_config.options, DHCP_LEASE_TIME);   option = find_option(server_config.options, DHCP_LEASE_TIME);
85   server_config.lease = LEASE_TIME;   server_config.max_lease_sec = LEASE_TIME;
86   if (option) {   if (option) {
87   memcpy(&server_config.lease, option->data + 2, 4);   move_from_unaligned32(server_config.max_lease_sec, option->data + OPT_DATA);
88   server_config.lease = ntohl(server_config.lease);   server_config.max_lease_sec = ntohl(server_config.max_lease_sec);
89   }   }
90    
91   /* Sanity check */   /* Sanity check */
# Line 91  int udhcpd_main(int argc UNUSED_PARAM, c Line 96  int udhcpd_main(int argc UNUSED_PARAM, c
96   server_config.max_leases = num_ips;   server_config.max_leases = num_ips;
97   }   }
98    
99   leases = xzalloc(server_config.max_leases * sizeof(*leases));   g_leases = xzalloc(server_config.max_leases * sizeof(g_leases[0]));
100   read_leases(server_config.lease_file);   read_leases(server_config.lease_file);
101    
102   if (udhcp_read_interface(server_config.interface, &server_config.ifindex,   if (udhcp_read_interface(server_config.interface,
103     &server_config.server, server_config.arp)) {   &server_config.ifindex,
104     &server_config.server_nip,
105     server_config.server_mac)
106     ) {
107   retval = 1;   retval = 1;
108   goto ret;   goto ret;
109   }   }
# Line 105  int udhcpd_main(int argc UNUSED_PARAM, c Line 113  int udhcpd_main(int argc UNUSED_PARAM, c
113    
114   timeout_end = monotonic_sec() + server_config.auto_time;   timeout_end = monotonic_sec() + server_config.auto_time;
115   while (1) { /* loop until universe collapses */   while (1) { /* loop until universe collapses */
116     int bytes;
117     struct timeval tv;
118    
119   if (server_socket < 0) {   if (server_socket < 0) {
120   server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT,   server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT,
# Line 127  int udhcpd_main(int argc UNUSED_PARAM, c Line 137  int udhcpd_main(int argc UNUSED_PARAM, c
137   continue;   continue;
138   }   }
139   if (retval < 0 && errno != EINTR) {   if (retval < 0 && errno != EINTR) {
140   DEBUG("error on select");   log1("Error on select");
141   continue;   continue;
142   }   }
143    
# Line 141  int udhcpd_main(int argc UNUSED_PARAM, c Line 151  int udhcpd_main(int argc UNUSED_PARAM, c
151   case SIGTERM:   case SIGTERM:
152   bb_info_msg("Received a SIGTERM");   bb_info_msg("Received a SIGTERM");
153   goto ret0;   goto ret0;
154   case 0: break; /* no signal */   case 0: /* no signal: read a packet */
155   default: continue; /* signal or error (probably EINTR) */   break;
156     default: /* signal or error (probably EINTR): back to select */
157     continue;
158   }   }
159    
160   bytes = udhcp_recv_kernel_packet(&packet, server_socket); /* this waits for a packet - idle */   bytes = udhcp_recv_kernel_packet(&packet, server_socket);
161   if (bytes < 0) {   if (bytes < 0) {
162     /* bytes can also be -2 ("bad packet data") */
163   if (bytes == -1 && errno != EINTR) {   if (bytes == -1 && errno != EINTR) {
164   DEBUG("error on read, %s, reopening socket", strerror(errno));   log1("Read error: %s, reopening socket", strerror(errno));
165   close(server_socket);   close(server_socket);
166   server_socket = -1;   server_socket = -1;
167   }   }
168   continue;   continue;
169   }   }
170    
171     if (packet.hlen != 6) {
172     bb_error_msg("MAC length != 6, ignoring packet");
173     continue;
174     }
175    
176   state = get_option(&packet, DHCP_MESSAGE_TYPE);   state = get_option(&packet, DHCP_MESSAGE_TYPE);
177   if (state == NULL) {   if (state == NULL) {
178   bb_error_msg("cannot get option from packet, ignoring");   bb_error_msg("no message type option, ignoring packet");
179   continue;   continue;
180   }   }
181    
182   /* Look for a static lease */   /* Look for a static lease */
183   static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr);   static_lease_ip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr);
   
184   if (static_lease_ip) {   if (static_lease_ip) {
185   bb_info_msg("Found static lease: %x", static_lease_ip);   bb_info_msg("Found static lease: %x", static_lease_ip);
186    
187   memcpy(&static_lease.chaddr, &packet.chaddr, 16);   memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
188   static_lease.yiaddr = static_lease_ip;   fake_lease.lease_nip = static_lease_ip;
189   static_lease.expires = 0;   fake_lease.expires = 0;
190    
191   lease = &static_lease;   lease = &fake_lease;
192   } else {   } else {
193   lease = find_lease_by_chaddr(packet.chaddr);   lease = find_lease_by_mac(packet.chaddr);
194   }   }
195    
196   switch (state[0]) {   switch (state[0]) {
197   case DHCPDISCOVER:   case DHCPDISCOVER:
198   DEBUG("Received DISCOVER");   log1("Received DISCOVER");
199    
200   if (send_offer(&packet) < 0) {   if (send_offer(&packet) < 0) {
201   bb_error_msg("send OFFER failed");   bb_error_msg("send OFFER failed");
202   }   }
203   break;   break;
204   case DHCPREQUEST:   case DHCPREQUEST: {
205   DEBUG("received REQUEST");   uint8_t *server_id_opt, *requested_opt;
206     uint32_t server_id_net = server_id_net; /* for compiler */
207   requested = get_option(&packet, DHCP_REQUESTED_IP);   uint32_t requested_nip = requested_nip; /* for compiler */
208   server_id = get_option(&packet, DHCP_SERVER_ID);  
209     log1("Received REQUEST");
210   if (requested) memcpy(&requested_align, requested, 4);  
211   if (server_id) memcpy(&server_id_align, server_id, 4);   requested_opt = get_option(&packet, DHCP_REQUESTED_IP);
212     server_id_opt = get_option(&packet, DHCP_SERVER_ID);
213     if (requested_opt)
214     move_from_unaligned32(requested_nip, requested_opt);
215     if (server_id_opt)
216     move_from_unaligned32(server_id_net, server_id_opt);
217    
218   if (lease) {   if (lease) {
219   if (server_id) {   if (server_id_opt) {
220   /* SELECTING State */   /* SELECTING State */
221   DEBUG("server_id = %08x", ntohl(server_id_align));   if (server_id_net == server_config.server_nip
222   if (server_id_align == server_config.server && requested   && requested_opt
223   && requested_align == lease->yiaddr   && requested_nip == lease->lease_nip
224   ) {   ) {
225   send_ACK(&packet, lease->yiaddr);   send_ACK(&packet, lease->lease_nip);
226   }   }
227   } else if (requested) {   } else if (requested_opt) {
228   /* INIT-REBOOT State */   /* INIT-REBOOT State */
229   if (lease->yiaddr == requested_align)   if (lease->lease_nip == requested_nip)
230   send_ACK(&packet, lease->yiaddr);   send_ACK(&packet, lease->lease_nip);
231   else   else
232   send_NAK(&packet);   send_NAK(&packet);
233   } else if (lease->yiaddr == packet.ciaddr) {   } else if (lease->lease_nip == packet.ciaddr) {
234   /* RENEWING or REBINDING State */   /* RENEWING or REBINDING State */
235   send_ACK(&packet, lease->yiaddr);   send_ACK(&packet, lease->lease_nip);
236   } else { /* don't know what to do!!!! */   } else { /* don't know what to do!!!! */
237   send_NAK(&packet);   send_NAK(&packet);
238   }   }
239    
240   /* what to do if we have no record of the client */   /* what to do if we have no record of the client */
241   } else if (server_id) {   } else if (server_id_opt) {
242   /* SELECTING State */   /* SELECTING State */
243    
244   } else if (requested) {   } else if (requested_opt) {
245   /* INIT-REBOOT State */   /* INIT-REBOOT State */
246   lease = find_lease_by_yiaddr(requested_align);   lease = find_lease_by_nip(requested_nip);
247   if (lease) {   if (lease) {
248   if (lease_expired(lease)) {   if (is_expired_lease(lease)) {
249   /* probably best if we drop this lease */   /* probably best if we drop this lease */
250   memset(lease->chaddr, 0, 16);   memset(lease->lease_mac, 0, sizeof(lease->lease_mac));
251   /* make some contention for this address */   } else {
252   } else   /* make some contention for this address */
253   send_NAK(&packet);   send_NAK(&packet);
254     }
255   } else {   } else {
256   uint32_t r = ntohl(requested_align);   uint32_t r = ntohl(requested_nip);
257   if (r < server_config.start_ip   if (r < server_config.start_ip
258           || r > server_config.end_ip           || r > server_config.end_ip
259   ) {   ) {
# Line 243  int udhcpd_main(int argc UNUSED_PARAM, c Line 266  int udhcpd_main(int argc UNUSED_PARAM, c
266   /* RENEWING or REBINDING State */   /* RENEWING or REBINDING State */
267   }   }
268   break;   break;
269     }
270   case DHCPDECLINE:   case DHCPDECLINE:
271   DEBUG("Received DECLINE");   log1("Received DECLINE");
272   if (lease) {   if (lease) {
273   memset(lease->chaddr, 0, 16);   memset(lease->lease_mac, 0, sizeof(lease->lease_mac));
274   lease->expires = time(0) + server_config.decline_time;   lease->expires = time(NULL) + server_config.decline_time;
275   }   }
276   break;   break;
277   case DHCPRELEASE:   case DHCPRELEASE:
278   DEBUG("Received RELEASE");   log1("Received RELEASE");
279   if (lease)   if (lease)
280   lease->expires = time(0);   lease->expires = time(NULL);
281   break;   break;
282   case DHCPINFORM:   case DHCPINFORM:
283   DEBUG("Received INFORM");   log1("Received INFORM");
284   send_inform(&packet);   send_inform(&packet);
285   break;   break;
286   default:   default:

Legend:
Removed from v.983  
changed lines
  Added in v.984