Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/networking/udhcp/dhcprelay.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 11  Line 11 
11   */   */
12    
13  #include "common.h"  #include "common.h"
 #include "dhcpd.h"  
14  #include "options.h"  #include "options.h"
15    
16  /* constants */  /* constants */
17  #define SELECT_TIMEOUT 5 /* select timeout in sec. */  #define SERVER_PORT      67
18  #define MAX_LIFETIME 2*60 /* lifetime of an xid entry in sec. */  #define SELECT_TIMEOUT    5 /* select timeout in sec. */
19  #define MAX_INTERFACES 9  #define MAX_LIFETIME   2*60 /* lifetime of an xid entry in sec. */
   
20    
21  /* This list holds information about clients. The xid_* functions manipulate this list. */  /* This list holds information about clients. The xid_* functions manipulate this list. */
22  static struct xid_item {  struct xid_item {
23   u_int32_t xid;   unsigned timestamp;
  struct sockaddr_in ip;  
24   int client;   int client;
25   time_t timestamp;   uint32_t xid;
26     struct sockaddr_in ip;
27   struct xid_item *next;   struct xid_item *next;
28  } dhcprelay_xid_list = {0, {0}, 0, 0, NULL};  };
29    
30    #define dhcprelay_xid_list (*(struct xid_item*)&bb_common_bufsiz1)
31    
32  static struct xid_item * xid_add(u_int32_t xid, struct sockaddr_in *ip, int client)  static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, int client)
33  {  {
34   struct xid_item *item;   struct xid_item *item;
35    
# Line 41  static struct xid_item * xid_add(u_int32 Line 40  static struct xid_item * xid_add(u_int32
40   item->ip = *ip;   item->ip = *ip;
41   item->xid = xid;   item->xid = xid;
42   item->client = client;   item->client = client;
43   item->timestamp = time(NULL);   item->timestamp = monotonic_sec();
44   item->next = dhcprelay_xid_list.next;   item->next = dhcprelay_xid_list.next;
45   dhcprelay_xid_list.next = item;   dhcprelay_xid_list.next = item;
46    
47   return item;   return item;
48  }  }
49    
   
50  static void xid_expire(void)  static void xid_expire(void)
51  {  {
52   struct xid_item *item = dhcprelay_xid_list.next;   struct xid_item *item = dhcprelay_xid_list.next;
53   struct xid_item *last = &dhcprelay_xid_list;   struct xid_item *last = &dhcprelay_xid_list;
54   time_t current_time = time(NULL);   unsigned current_time = monotonic_sec();
55    
56   while (item != NULL) {   while (item != NULL) {
57   if ((current_time-item->timestamp) > MAX_LIFETIME) {   if ((current_time - item->timestamp) > MAX_LIFETIME) {
58   last->next = item->next;   last->next = item->next;
59   free(item);   free(item);
60   item = last->next;   item = last->next;
# Line 67  static void xid_expire(void) Line 65  static void xid_expire(void)
65   }   }
66  }  }
67    
68  static struct xid_item * xid_find(u_int32_t xid)  static struct xid_item *xid_find(uint32_t xid)
69  {  {
70   struct xid_item *item = dhcprelay_xid_list.next;   struct xid_item *item = dhcprelay_xid_list.next;
71   while (item != NULL) {   while (item != NULL) {
# Line 79  static struct xid_item * xid_find(u_int3 Line 77  static struct xid_item * xid_find(u_int3
77   return NULL;   return NULL;
78  }  }
79    
80  static void xid_del(u_int32_t xid)  static void xid_del(uint32_t xid)
81  {  {
82   struct xid_item *item = dhcprelay_xid_list.next;   struct xid_item *item = dhcprelay_xid_list.next;
83   struct xid_item *last = &dhcprelay_xid_list;   struct xid_item *last = &dhcprelay_xid_list;
# Line 95  static void xid_del(u_int32_t xid) Line 93  static void xid_del(u_int32_t xid)
93   }   }
94  }  }
95    
   
96  /**  /**
97   * get_dhcp_packet_type - gets the message type of a dhcp packet   * get_dhcp_packet_type - gets the message type of a dhcp packet
98   * p - pointer to the dhcp packet   * p - pointer to the dhcp packet
# Line 116  static int get_dhcp_packet_type(struct d Line 113  static int get_dhcp_packet_type(struct d
113  }  }
114    
115  /**  /**
  * signal_handler - handles signals ;-)  
  * sig - sent signal  
  */  
 static int dhcprelay_stopflag;  
 static void dhcprelay_signal_handler(int sig)  
 {  
  dhcprelay_stopflag = 1;  
 }  
   
 /**  
116   * get_client_devices - parses the devices list   * get_client_devices - parses the devices list
117   * dev_list - comma separated list of devices   * dev_list - comma separated list of devices
118   * returns array   * returns array
119   */   */
120  static char ** get_client_devices(char *dev_list, int *client_number)  static char **get_client_devices(char *dev_list, int *client_number)
121  {  {
122   char *s, *list, **client_dev;   char *s, **client_dev;
123   int i, cn;   int i, cn;
124    
125   /* copy list */   /* copy list */
126   list = xstrdup(dev_list);   dev_list = xstrdup(dev_list);
  if (list == NULL) return NULL;  
127    
128   /* get number of items */   /* get number of items, replace ',' with NULs */
129   for (s = dev_list, cn = 1; *s; s++)   s = dev_list;
130   if (*s == ',')   cn = 1;
131     while (*s) {
132     if (*s == ',') {
133     *s = '\0';
134   cn++;   cn++;
135     }
136     s++;
137     }
138     *client_number = cn;
139    
140     /* create vector of pointers */
141   client_dev = xzalloc(cn * sizeof(*client_dev));   client_dev = xzalloc(cn * sizeof(*client_dev));
142     client_dev[0] = dev_list;
143   /* parse list */   i = 1;
144   s = strtok(list, ",");   while (i != cn) {
145   i = 0;   client_dev[i] = client_dev[i - 1] + strlen(client_dev[i - 1]) + 1;
146   while (s != NULL) {   i++;
  client_dev[i++] = xstrdup(s);  
  s = strtok(NULL, ",");  
147   }   }
   
  /* free copy and exit */  
  free(list);  
  *client_number = cn;  
148   return client_dev;   return client_dev;
149  }  }
150    
151    
152  /* Creates listen sockets (in fds) and returns the number allocated. */  /* Creates listen sockets (in fds) and returns numerically max fd. */
153  static int init_sockets(char **client, int num_clients,  static int init_sockets(char **client, int num_clients,
154   char *server, int *fds, int *max_socket)   char *server, int *fds)
155  {  {
156   int i;   int i, n;
157    
158   /* talk to real server on bootps */   /* talk to real server on bootps */
159   fds[0] = listen_socket(htonl(INADDR_ANY), 67, server);   fds[0] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server);
160   *max_socket = fds[0];   n = fds[0];
   
  /* array starts at 1 since server is 0 */  
  num_clients++;  
161    
162   for (i=1; i < num_clients; i++) {   for (i = 1; i < num_clients; i++) {
163   /* listen for clients on bootps */   /* listen for clients on bootps */
164   fds[i] = listen_socket(htonl(INADDR_ANY), 67, client[i-1]);   fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client[i-1]);
165   if (fds[i] > *max_socket) *max_socket = fds[i];   if (fds[i] > n)
166     n = fds[i];
167   }   }
168     return n;
  return i;  
169  }  }
170    
171    
# Line 239  static void pass_back(struct dhcpMessage Line 224  static void pass_back(struct dhcpMessage
224    
225   if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY))   if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY))
226   item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST);   item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST);
  if (item->client > MAX_INTERFACES)  
  return;  
227   res = sendto(fds[item->client], p, packet_len, 0, (struct sockaddr*)(&item->ip),   res = sendto(fds[item->client], p, packet_len, 0, (struct sockaddr*)(&item->ip),
228   sizeof(item->ip));   sizeof(item->ip));
229   if (res != packet_len) {   if (res != packet_len) {
# Line 253  static void pass_back(struct dhcpMessage Line 236  static void pass_back(struct dhcpMessage
236  }  }
237    
238  static void dhcprelay_loop(int *fds, int num_sockets, int max_socket, char **clients,  static void dhcprelay_loop(int *fds, int num_sockets, int max_socket, char **clients,
239     struct sockaddr_in *server_addr, uint32_t gw_ip) NORETURN;
240    static void dhcprelay_loop(int *fds, int num_sockets, int max_socket, char **clients,
241   struct sockaddr_in *server_addr, uint32_t gw_ip)   struct sockaddr_in *server_addr, uint32_t gw_ip)
242  {  {
243   struct dhcpMessage dhcp_msg;   struct dhcpMessage dhcp_msg;
# Line 263  static void dhcprelay_loop(int *fds, int Line 248  static void dhcprelay_loop(int *fds, int
248   struct timeval tv;   struct timeval tv;
249   int i;   int i;
250    
251   while (!dhcprelay_stopflag) {   while (1) {
252   FD_ZERO(&rfds);   FD_ZERO(&rfds);
253   for (i = 0; i < num_sockets; i++)   for (i = 0; i < num_sockets; i++)
254   FD_SET(fds[i], &rfds);   FD_SET(fds[i], &rfds);
# Line 272  static void dhcprelay_loop(int *fds, int Line 257  static void dhcprelay_loop(int *fds, int
257   if (select(max_socket + 1, &rfds, NULL, NULL, &tv) > 0) {   if (select(max_socket + 1, &rfds, NULL, NULL, &tv) > 0) {
258   /* server */   /* server */
259   if (FD_ISSET(fds[0], &rfds)) {   if (FD_ISSET(fds[0], &rfds)) {
260   packlen = udhcp_get_packet(&dhcp_msg, fds[0]);   packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]);
261   if (packlen > 0) {   if (packlen > 0) {
262   pass_back(&dhcp_msg, packlen, fds);   pass_back(&dhcp_msg, packlen, fds);
263   }   }
# Line 286  static void dhcprelay_loop(int *fds, int Line 271  static void dhcprelay_loop(int *fds, int
271   (struct sockaddr *)(&client_addr), &addr_size);   (struct sockaddr *)(&client_addr), &addr_size);
272   if (packlen <= 0)   if (packlen <= 0)
273   continue;   continue;
274   if (read_interface(clients[i-1], NULL, &dhcp_msg.giaddr, NULL) < 0)   if (udhcp_read_interface(clients[i-1], NULL, &dhcp_msg.giaddr, NULL))
275   dhcp_msg.giaddr = gw_ip;   dhcp_msg.giaddr = gw_ip;
276   pass_on(&dhcp_msg, packlen, i, fds, &client_addr, server_addr);   pass_on(&dhcp_msg, packlen, i, fds, &client_addr, server_addr);
277   }   }
# Line 295  static void dhcprelay_loop(int *fds, int Line 280  static void dhcprelay_loop(int *fds, int
280   }   }
281  }  }
282    
283    int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
284  int dhcprelay_main(int argc, char **argv)  int dhcprelay_main(int argc, char **argv)
285  {  {
286   int i, num_sockets, max_socket, fds[MAX_INTERFACES];   int num_sockets, max_socket;
287     int *fds;
288   uint32_t gw_ip;   uint32_t gw_ip;
289   char **clients;   char **clients;
290   struct sockaddr_in server_addr;   struct sockaddr_in server_addr;
291    
292   server_addr.sin_family = AF_INET;   server_addr.sin_family = AF_INET;
293   server_addr.sin_port = htons(67);   server_addr.sin_port = htons(SERVER_PORT);
294   if (argc == 4) {   if (argc == 4) {
295   if (!inet_aton(argv[3], &server_addr.sin_addr))   if (!inet_aton(argv[3], &server_addr.sin_addr))
296   bb_perror_msg_and_die("didn't grok server");   bb_perror_msg_and_die("didn't grok server");
# Line 312  int dhcprelay_main(int argc, char **argv Line 299  int dhcprelay_main(int argc, char **argv
299   } else {   } else {
300   bb_show_usage();   bb_show_usage();
301   }   }
  clients = get_client_devices(argv[1], &num_sockets);  
  if (!clients) return 0;  
   
  signal(SIGTERM, dhcprelay_signal_handler);  
  signal(SIGQUIT, dhcprelay_signal_handler);  
  signal(SIGINT, dhcprelay_signal_handler);  
302    
303   num_sockets = init_sockets(clients, num_sockets, argv[2], fds, &max_socket);   clients = get_client_devices(argv[1], &num_sockets);
304     num_sockets++; /* for server socket at fds[0] */
305     fds = xmalloc(num_sockets * sizeof(fds[0]));
306     max_socket = init_sockets(clients, num_sockets, argv[2], fds);
307    
308   if (read_interface(argv[2], NULL, &gw_ip, NULL) == -1)   if (udhcp_read_interface(argv[2], NULL, &gw_ip, NULL))
309   return 1;   return 1;
310    
311     /* doesn't return */
312   dhcprelay_loop(fds, num_sockets, max_socket, clients, &server_addr, gw_ip);   dhcprelay_loop(fds, num_sockets, max_socket, clients, &server_addr, gw_ip);
313     /* return 0; - not reached */
  if (ENABLE_FEATURE_CLEAN_UP) {  
  for (i = 0; i < num_sockets; i++) {  
  close(fds[i]);  
  free(clients[i]);  
  }  
  }  
   
  return 0;  
314  }  }

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