5f719f478b8313dcbebb462dbd0e518e5d5a3b0e
[olsrd.git] / src / olsr.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /**
43  * All these functions are global
44  */
45
46 #include "defs.h"
47 #include "olsr.h"
48 #include "link_set.h"
49 #include "tc_set.h"
50 #include "duplicate_set.h"
51 #include "mid_set.h"
52 #include "lq_mpr.h"
53 #include "olsr_spf.h"
54 #include "olsr_timer.h"
55 #include "olsr_socket.h"
56 #include "neighbor_table.h"
57 #include "lq_packet.h"
58 #include "common/avl.h"
59 #include "net_olsr.h"
60 #include "lq_plugin.h"
61 #include "olsr_logging.h"
62 #include "os_system.h"
63 #include "os_apm.h"
64
65 #include <assert.h>
66 #include <stdarg.h>
67 #include <unistd.h>
68 #include <stdlib.h>
69
70 static void olsr_update_willingness(void *);
71
72 bool changes_topology = false;
73 bool changes_neighborhood = false;
74 bool changes_hna = false;
75 bool changes_force = false;
76
77 static uint16_t message_seqno;
78
79 /**
80  *Initialize the message sequence number as a random value
81  */
82 void
83 init_msg_seqno(void)
84 {
85   message_seqno = random() & 0xFFFF;
86   OLSR_DEBUG(LOG_MAIN, "Settings initial message sequence number to %u\n", message_seqno);
87 }
88
89 /**
90  * Get and increment the message sequence number
91  *
92  *@return the seqno
93  */
94 uint16_t
95 get_msg_seqno(void)
96 {
97   return message_seqno++;
98 }
99
100 /**
101  *Process changes in neighborhood or/and topology.
102  *Re-calculates the neighborhood/topology if there
103  *are any updates - then calls the right functions to
104  *update the routing table.
105  *@return 0
106  */
107 void
108 olsr_process_changes(void)
109 {
110   if (changes_neighborhood)
111     OLSR_DEBUG(LOG_MAIN, "CHANGES IN NEIGHBORHOOD\n");
112   if (changes_topology)
113     OLSR_DEBUG(LOG_MAIN, "CHANGES IN TOPOLOGY\n");
114   if (changes_hna)
115     OLSR_DEBUG(LOG_MAIN, "CHANGES IN HNA\n");
116
117   if (!changes_neighborhood && !changes_topology && !changes_hna)
118     return;
119
120   if (olsr_cnf->log_target_stderr && olsr_cnf->clear_screen && isatty(STDOUT_FILENO)) {
121     os_clear_console();
122     printf("       *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host);
123   }
124
125   if (changes_neighborhood) {
126     olsr_calculate_lq_mpr();
127   }
128
129   /* calculate the routing table */
130   if (changes_neighborhood || changes_topology || changes_hna) {
131     olsr_calculate_routing_table(false);
132   }
133
134   olsr_print_link_set();
135   olsr_print_neighbor_table();
136   olsr_print_tc_table();
137   olsr_print_mid_set();
138   olsr_print_duplicate_table();
139   olsr_print_hna_set();
140
141   changes_neighborhood = false;
142   changes_topology = false;
143   changes_hna = false;
144   changes_force = false;
145 }
146
147 /**
148  * Shared code to write the message header
149  */
150 uint8_t *
151 olsr_put_msg_hdr(uint8_t **curr, struct olsr_message *msg)
152 {
153   uint8_t *sizeptr;
154
155   assert(msg);
156   assert(curr);
157
158   pkt_put_u8(curr, msg->type);
159   pkt_put_reltime(curr, msg->vtime);
160   sizeptr = *curr;
161   pkt_put_u16(curr, msg->size);
162   pkt_put_ipaddress(curr, &msg->originator);
163   pkt_put_u8(curr, msg->ttl);
164   pkt_put_u8(curr, msg->hopcnt);
165   pkt_put_u16(curr, msg->seqno);
166
167   return sizeptr;
168 }
169
170 static void
171 olsr_update_willingness(void *foo __attribute__ ((unused)))
172 {
173   int tmp_will = olsr_cnf->willingness;
174
175   /* Re-calculate willingness */
176   olsr_calculate_willingness();
177
178   if (tmp_will != olsr_cnf->willingness) {
179     OLSR_INFO(LOG_MAIN, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
180   }
181 }
182
183 void
184 olsr_init_willingness(void)
185 {
186   /* Some cookies for stats keeping */
187   static struct olsr_timer_info *willingness_timer_info = NULL;
188
189   if (olsr_cnf->willingness_auto) {
190     OLSR_INFO(LOG_MAIN, "Initialize automatic willingness...\n");
191     /* Run it first and then periodic. */
192     olsr_update_willingness(NULL);
193
194     willingness_timer_info = olsr_timer_add("Update Willingness", &olsr_update_willingness, true);
195     olsr_timer_start(olsr_cnf->will_int, 5, NULL, willingness_timer_info);
196   }
197 }
198
199 /**
200  *Calculate this nodes willingness to act as a MPR
201  *based on either a fixed value or the power status
202  *of the node using APM
203  *
204  *@return a 8bit value from 0-7 representing the willingness
205  */
206
207 void
208 olsr_calculate_willingness(void)
209 {
210   struct olsr_apm_info ainfo;
211 #if !defined(REMOVE_LOG_INFO)
212   struct millitxt_buf tbuf;
213 #endif
214
215   /* If fixed willingness */
216   if (!olsr_cnf->willingness_auto)
217     return;
218
219   if (os_apm_read(&ainfo) < 1) {
220     olsr_cnf->willingness = WILL_DEFAULT;
221     olsr_cnf->willingness_auto = false;
222     OLSR_WARN(LOG_MAIN, "Cannot read APM info, setting willingness to default value (%d)", olsr_cnf->willingness);
223     return;
224   }
225
226   os_apm_printinfo(&ainfo);
227
228   /* If AC powered */
229   if (ainfo.ac_line_status == OLSR_AC_POWERED) {
230     olsr_cnf->willingness = 6;
231   }
232   else {
233   /* If battery powered
234    *
235    * juice > 78% will: 3
236    * 78% > juice > 26% will: 2
237    * 26% > juice will: 1
238    */
239     olsr_cnf->willingness = (ainfo.battery_percentage / 26);
240   }
241   OLSR_INFO(LOG_MAIN, "Willingness set to %d - next update in %s secs\n",
242       olsr_cnf->willingness, olsr_milli_to_txt(&tbuf, olsr_cnf->will_int));
243 }
244
245 /**
246  *Termination function to be called whenever a error occures
247  *that requires the daemon to terminate
248  *
249  *@param val the exit code for OLSR
250  */
251
252 void
253 olsr_exit(int val)
254 {
255   fflush(stdout);
256   olsr_cnf->exit_value = val;
257   if (app_state == STATE_INIT) {
258     os_exit(val);
259   }
260   app_state = STATE_SHUTDOWN;
261 }
262
263
264 /**
265  * Wrapper for malloc(3) that does error-checking
266  *
267  * @param size the number of bytes to allocalte
268  * @param caller a string identifying the caller for
269  * use in error messaging
270  *
271  * @return a void pointer to the memory allocated
272  */
273 void *
274 olsr_malloc(size_t size, const char *id __attribute__ ((unused)))
275 {
276   void *ptr;
277
278   /*
279    * Not all the callers do a proper cleaning of memory.
280    * Clean it on behalf of those.
281    */
282   ptr = calloc(1, size);
283
284   if (!ptr) {
285     OLSR_ERROR(LOG_MAIN, "Out of memory for id '%s': %s\n", id, strerror(errno));
286     olsr_exit(EXIT_FAILURE);
287   }
288   return ptr;
289 }
290
291 /*
292  * Same as strdup but works with olsr_malloc
293  */
294 char *
295 olsr_strdup(const char *s)
296 {
297   char *ret = olsr_malloc(1 + strlen(s), "olsr_strdup");
298   strcpy(ret, s);
299   return ret;
300 }
301
302 /*
303  * Same as strndup but works with olsr_malloc
304  */
305 char *
306 olsr_strndup(const char *s, size_t n)
307 {
308   size_t len = n < strlen(s) ? n : strlen(s);
309   char *ret = olsr_malloc(1 + len, "olsr_strndup");
310   strncpy(ret, s, len);
311   ret[len] = 0;
312   return ret;
313 }
314
315 /*
316  * Local Variables:
317  * c-basic-offset: 2
318  * indent-tabs-mode: nil
319  * End:
320  */