More Logger stuff
[olsrd.git] / src / build_msg.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include "build_msg.h"
42 #include "ipcalc.h"
43 #include "olsr.h"
44 #include "log.h"
45 #include "mantissa.h"
46 #include "net_olsr.h"
47 #include "olsr_ip_prefix_list.h"
48
49 #include <stdlib.h>
50
51 #define OLSR_IPV4_HDRSIZE          12
52 #define OLSR_IPV6_HDRSIZE          24
53
54 #define OLSR_HELLO_IPV4_HDRSIZE    (OLSR_IPV4_HDRSIZE + 4)
55 #define OLSR_HELLO_IPV6_HDRSIZE    (OLSR_IPV6_HDRSIZE + 4)
56 #define OLSR_TC_IPV4_HDRSIZE       (OLSR_IPV4_HDRSIZE + 4)
57 #define OLSR_TC_IPV6_HDRSIZE       (OLSR_IPV6_HDRSIZE + 4)
58 #define OLSR_MID_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
59 #define OLSR_MID_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
60 #define OLSR_HNA_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
61 #define OLSR_HNA_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
62
63 static void
64 check_buffspace(int msgsize, int buffsize, const char *type);
65
66 /* All these functions share this buffer */
67
68 static uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
69
70 /* Prototypes for internal functions */
71
72 /* IPv4 */
73
74 static bool
75 serialize_mid4(struct interface *);
76
77 static bool
78 serialize_hna4(struct interface *);
79
80 /* IPv6 */
81
82 static bool
83 serialize_mid6(struct interface *);
84
85 static bool
86 serialize_hna6(struct interface *);
87
88 /**
89  *Build a MID message to the outputbuffer
90  *
91  *<b>NO INTERNAL BUFFER</b>
92  *@param ifn use this interfaces address as main address
93  *@return 1 on success
94  */
95
96 bool
97 queue_mid(struct interface *ifp)
98 {
99   OLSR_INFO(LOG_PACKET_CREATION, "Building MID on %s\n-------------------\n", ifp->int_name);
100
101   switch(olsr_cnf->ip_version)
102     {
103     case(AF_INET):
104       return serialize_mid4(ifp);
105     case(AF_INET6):
106       return serialize_mid6(ifp);
107     }
108   return false;
109 }
110
111
112 /**
113  *Builds a HNA message in the outputbuffer
114  *<b>NB! Not internal packetformat!</b>
115  *
116  *@param ifp the interface to send on
117  *@return nada
118  */
119 bool
120 queue_hna(struct interface *ifp)
121 {
122   OLSR_INFO(LOG_PACKET_CREATION, "Building HNA on %s\n-------------------\n", ifp->int_name);
123
124   switch(olsr_cnf->ip_version)
125     {
126     case(AF_INET):
127       return serialize_hna4(ifp);
128     case(AF_INET6):
129       return serialize_hna6(ifp);
130     }
131   return false;
132 }
133
134 /*
135  * Protocol specific versions
136  */
137
138
139 static void
140 check_buffspace(int msgsize, int buffsize, const char *type __attribute__ ((unused)))
141 {
142   if(msgsize > buffsize)
143     {
144       OLSR_ERROR(LOG_PACKET_CREATION, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
145       olsr_exit(EXIT_FAILURE);
146     }
147 }
148
149 /**
150  *IP version 4
151  *
152  *<b>NO INTERNAL BUFFER</b>
153  *@param ifp use this interfaces address as main address
154  *@return 1 on success
155  */
156
157 static bool
158 serialize_mid4(struct interface *ifp)
159 {
160   uint16_t remainsize, curr_size;
161   /* preserve existing data in output buffer */
162   union olsr_message *m;
163   struct midaddr *addrs;
164   struct interface *ifs;
165 #if !defined REMOVE_DEBUG
166   struct ipaddr_str buf;
167 #endif
168   if ((olsr_cnf->ip_version != AF_INET) || (!ifp) ||
169       list_is_empty(&interface_head)) {
170     return false;
171   }
172
173   remainsize = net_outbuffer_bytes_left(ifp);
174
175   m = (union olsr_message *)msg_buffer;
176
177   curr_size = OLSR_MID_IPV4_HDRSIZE;
178
179   /* Send pending packet if not room in buffer */
180   if(curr_size > remainsize)
181     {
182       net_output(ifp);
183       remainsize = net_outbuffer_bytes_left(ifp);
184     }
185   check_buffspace(curr_size, remainsize, "MID");
186
187   /* Fill header */
188   m->v4.hopcnt = 0;
189   m->v4.ttl = MAX_TTL;
190   /* Set main(first) address */
191   m->v4.originator = olsr_cnf->router_id.v4.s_addr;
192   m->v4.olsr_msgtype = MID_MESSAGE;
193   m->v4.olsr_vtime = ifp->valtimes.mid;
194
195   addrs = m->v4.message.mid.mid_addr;
196
197   /* Don't add the main address... it's already there */
198   OLSR_FOR_ALL_INTERFACES(ifs) {
199       if(!olsr_ipequal(&olsr_cnf->router_id, &ifs->ip_addr))
200         {
201           if((curr_size + olsr_cnf->ipsize) > remainsize)
202             {
203               /* Only add MID message if it contains data */
204               if(curr_size > OLSR_MID_IPV4_HDRSIZE)
205                 {
206                   OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
207                   /* set size */
208                   m->v4.olsr_msgsize = htons(curr_size);
209                   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
210
211                   net_outbuffer_push(ifp, msg_buffer, curr_size);
212                   curr_size = OLSR_MID_IPV4_HDRSIZE;
213                   addrs = m->v4.message.mid.mid_addr;
214                 }
215               net_output(ifp);
216               remainsize = net_outbuffer_bytes_left(ifp);
217               check_buffspace(curr_size, remainsize, "MID2");
218             }
219           OLSR_DEBUG(LOG_PACKET_CREATION, "\t%s(%s)\n",
220                       olsr_ip_to_string(&buf, &ifs->ip_addr),
221                       ifs->int_name);
222
223           addrs->addr = ifs->ip_addr.v4.s_addr;
224           addrs++;
225           curr_size += olsr_cnf->ipsize;
226         }
227   } OLSR_FOR_ALL_INTERFACES_END(ifs);
228
229
230   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
231   m->v4.olsr_msgsize = htons(curr_size);
232
233   if(curr_size > OLSR_MID_IPV4_HDRSIZE)
234     net_outbuffer_push(ifp, msg_buffer, curr_size);
235
236   return true;
237 }
238
239
240
241 /**
242  *IP version 6
243  *
244  *<b>NO INTERNAL BUFFER</b>
245  *@param ifp use this interfaces address as main address
246  *@return 1 on success
247  */
248
249 static bool
250 serialize_mid6(struct interface *ifp)
251 {
252   uint16_t remainsize, curr_size;
253   /* preserve existing data in output buffer */
254   union olsr_message *m;
255   struct midaddr6 *addrs6;
256   struct interface *ifs;
257 #if !defined REMOVE_DEBUG
258   struct ipaddr_str buf;
259 #endif
260
261   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) ||
262       list_is_empty(&interface_head)) {
263     return false;
264   }
265
266   remainsize = net_outbuffer_bytes_left(ifp);
267
268   curr_size = OLSR_MID_IPV6_HDRSIZE;
269
270   /* Send pending packet if not room in buffer */
271   if(curr_size > remainsize)
272     {
273       net_output(ifp);
274       remainsize = net_outbuffer_bytes_left(ifp);
275     }
276   check_buffspace(curr_size, remainsize, "MID");
277
278   m = (union olsr_message *)msg_buffer;
279
280   /* Build header */
281   m->v6.hopcnt = 0;
282   m->v6.ttl = MAX_TTL;
283   m->v6.olsr_msgtype = MID_MESSAGE;
284   m->v6.olsr_vtime = ifp->valtimes.mid;
285   /* Set main(first) address */
286   m->v6.originator = olsr_cnf->router_id.v6;
287
288   addrs6 = m->v6.message.mid.mid_addr;
289
290   /* Don't add the main address... it's already there */
291   OLSR_FOR_ALL_INTERFACES(ifs) {
292       if(!olsr_ipequal(&olsr_cnf->router_id, &ifs->ip_addr))
293         {
294           if((curr_size + olsr_cnf->ipsize) > remainsize)
295             {
296               /* Only add MID message if it contains data */
297               if(curr_size > OLSR_MID_IPV6_HDRSIZE)
298                 {
299                   OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
300                   /* set size */
301                   m->v6.olsr_msgsize = htons(curr_size);
302                   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
303
304                   net_outbuffer_push(ifp, msg_buffer, curr_size);
305                   curr_size = OLSR_MID_IPV6_HDRSIZE;
306                   addrs6 = m->v6.message.mid.mid_addr;
307                 }
308               net_output(ifp);
309               remainsize = net_outbuffer_bytes_left(ifp);
310               check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
311             }
312                   OLSR_DEBUG(LOG_PACKET_CREATION, "\t%s(%s)\n",
313                               olsr_ip_to_string(&buf, &ifs->ip_addr),
314                               ifs->int_name);
315
316           addrs6->addr = ifs->ip_addr.v6;
317           addrs6++;
318           curr_size += olsr_cnf->ipsize;
319         }
320   } OLSR_FOR_ALL_INTERFACES_END(ifs);
321
322   m->v6.olsr_msgsize = htons(curr_size);
323   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
324
325   if(curr_size > OLSR_MID_IPV6_HDRSIZE)
326     net_outbuffer_push(ifp, msg_buffer, curr_size);
327
328   return true;
329 }
330
331
332
333
334 /**
335  *IP version 4
336  *
337  *@param ifp the interface to send on
338  *@return nada
339  */
340 static bool
341 serialize_hna4(struct interface *ifp)
342 {
343   uint16_t remainsize, curr_size;
344   /* preserve existing data in output buffer */
345   union olsr_message *m;
346   struct hnapair *pair;
347   struct ip_prefix_entry *h;
348 #if !defined REMOVE_DEBUG
349   struct ipprefix_str prefixstr;
350 #endif
351   /* No hna nets */
352   if (ifp == NULL) {
353     return false;
354   }
355   if (olsr_cnf->ip_version != AF_INET) {
356     return false;
357   }
358   if (list_is_empty(&olsr_cnf->hna_entries)) {
359     return false;
360   }
361
362   remainsize = net_outbuffer_bytes_left(ifp);
363
364   curr_size = OLSR_HNA_IPV4_HDRSIZE;
365
366   /* Send pending packet if not room in buffer */
367   if(curr_size > remainsize)
368     {
369       net_output(ifp);
370       remainsize = net_outbuffer_bytes_left(ifp);
371     }
372   check_buffspace(curr_size, remainsize, "HNA");
373
374   m = (union olsr_message *)msg_buffer;
375
376
377   /* Fill header */
378   m->v4.originator = olsr_cnf->router_id.v4.s_addr;
379   m->v4.hopcnt = 0;
380   m->v4.ttl = MAX_TTL;
381   m->v4.olsr_msgtype = HNA_MESSAGE;
382   m->v4.olsr_vtime = ifp->valtimes.hna;
383
384
385   pair = m->v4.message.hna.hna_net;
386
387   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
388       union olsr_ip_addr ip_addr;
389       if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
390         {
391           /* Only add HNA message if it contains data */
392           if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
393             {
394               OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
395               m->v4.seqno = htons(get_msg_seqno());
396               m->v4.olsr_msgsize = htons(curr_size);
397               net_outbuffer_push(ifp, msg_buffer, curr_size);
398               curr_size = OLSR_HNA_IPV4_HDRSIZE;
399               pair = m->v4.message.hna.hna_net;
400             }
401           net_output(ifp);
402           remainsize = net_outbuffer_bytes_left(ifp);
403           check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
404         }
405       OLSR_DEBUG(LOG_PACKET_CREATION, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
406       pair->addr = h->net.prefix.v4.s_addr;
407       olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
408       pair->netmask = ip_addr.v4.s_addr;
409       pair++;
410       curr_size += (2 * olsr_cnf->ipsize);
411   } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
412
413   m->v4.seqno = htons(get_msg_seqno());
414   m->v4.olsr_msgsize = htons(curr_size);
415
416   net_outbuffer_push(ifp, msg_buffer, curr_size);
417
418   return false;
419 }
420
421
422 /**
423  *IP version 6
424  *
425  *@param ifp the interface to send on
426  *@return nada
427  */
428 static bool
429 serialize_hna6(struct interface *ifp)
430 {
431   uint16_t remainsize, curr_size;
432   /* preserve existing data in output buffer */
433   union olsr_message *m;
434   struct hnapair6 *pair6;
435   union olsr_ip_addr tmp_netmask;
436   struct ip_prefix_entry *h;
437 #if !defined REMOVE_DEBUG
438   struct ipprefix_str prefixstr;
439 #endif
440
441   /* No hna nets */
442   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || list_is_empty(&olsr_cnf->hna_entries))
443     return false;
444
445
446   remainsize = net_outbuffer_bytes_left(ifp);
447
448   curr_size = OLSR_HNA_IPV6_HDRSIZE;
449
450   /* Send pending packet if not room in buffer */
451   if(curr_size > remainsize)
452     {
453       net_output(ifp);
454       remainsize = net_outbuffer_bytes_left(ifp);
455     }
456   check_buffspace(curr_size, remainsize, "HNA");
457
458   m = (union olsr_message *)msg_buffer;
459
460   /* Fill header */
461   m->v6.originator = olsr_cnf->router_id.v6;
462   m->v6.hopcnt = 0;
463   m->v6.ttl = MAX_TTL;
464   m->v6.olsr_msgtype = HNA_MESSAGE;
465   m->v6.olsr_vtime = ifp->valtimes.hna;
466
467   pair6 = m->v6.message.hna.hna_net;
468
469
470   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
471       if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
472         {
473           /* Only add HNA message if it contains data */
474           if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
475             {
476               OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
477               m->v6.seqno = htons(get_msg_seqno());
478               m->v6.olsr_msgsize = htons(curr_size);
479               net_outbuffer_push(ifp, msg_buffer, curr_size);
480               curr_size = OLSR_HNA_IPV6_HDRSIZE;
481               pair6 = m->v6.message.hna.hna_net;
482             }
483           net_output(ifp);
484           remainsize = net_outbuffer_bytes_left(ifp);
485           check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
486         }
487       OLSR_DEBUG(LOG_PACKET_CREATION, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
488       pair6->addr = h->net.prefix.v6;
489       olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
490       pair6->netmask = tmp_netmask.v6;
491       pair6++;
492       curr_size += (2 * olsr_cnf->ipsize);
493     } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
494
495   m->v6.olsr_msgsize = htons(curr_size);
496   m->v6.seqno = htons(get_msg_seqno());
497
498   net_outbuffer_push(ifp, msg_buffer, curr_size);
499   return false;
500 }
501
502 /*
503  * Local Variables:
504  * c-basic-offset: 2
505  * indent-tabs-mode: nil
506  * End:
507  */