494462e81f62ceacf5f6cff6f497b69531d2e0c6
[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 BMSG_DBGLVL 5
52
53 #define OLSR_IPV4_HDRSIZE          12
54 #define OLSR_IPV6_HDRSIZE          24
55
56 #define OLSR_HELLO_IPV4_HDRSIZE    (OLSR_IPV4_HDRSIZE + 4)
57 #define OLSR_HELLO_IPV6_HDRSIZE    (OLSR_IPV6_HDRSIZE + 4)
58 #define OLSR_TC_IPV4_HDRSIZE       (OLSR_IPV4_HDRSIZE + 4)
59 #define OLSR_TC_IPV6_HDRSIZE       (OLSR_IPV6_HDRSIZE + 4)
60 #define OLSR_MID_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
61 #define OLSR_MID_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
62 #define OLSR_HNA_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
63 #define OLSR_HNA_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
64
65 static void
66 check_buffspace(int msgsize, int buffsize, const char *type);
67
68 /* All these functions share this buffer */
69
70 static uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
71
72 /* Prototypes for internal functions */
73
74 /* IPv4 */
75
76 static bool
77 serialize_mid4(struct interface *);
78
79 static bool
80 serialize_hna4(struct interface *);
81
82 /* IPv6 */
83
84 static bool
85 serialize_mid6(struct interface *);
86
87 static bool
88 serialize_hna6(struct interface *);
89
90 /**
91  *Build a MID message to the outputbuffer
92  *
93  *<b>NO INTERNAL BUFFER</b>
94  *@param ifn use this interfaces address as main address
95  *@return 1 on success
96  */
97
98 bool
99 queue_mid(struct interface *ifp)
100 {
101 #ifdef DEBUG
102   OLSR_PRINTF(BMSG_DBGLVL, "Building MID on %s\n-------------------\n", ifp->int_name);
103 #endif
104
105   switch(olsr_cnf->ip_version)
106     {
107     case(AF_INET):
108       return serialize_mid4(ifp);
109     case(AF_INET6):
110       return serialize_mid6(ifp);
111     }
112   return false;
113 }
114
115
116 /**
117  *Builds a HNA message in the outputbuffer
118  *<b>NB! Not internal packetformat!</b>
119  *
120  *@param ifp the interface to send on
121  *@return nada
122  */
123 bool
124 queue_hna(struct interface *ifp)
125 {
126 #ifdef DEBUG
127   OLSR_PRINTF(BMSG_DBGLVL, "Building HNA on %s\n-------------------\n", ifp->int_name);
128 #endif
129
130   switch(olsr_cnf->ip_version)
131     {
132     case(AF_INET):
133       return serialize_hna4(ifp);
134     case(AF_INET6):
135       return serialize_hna6(ifp);
136     }
137   return false;
138 }
139
140 /*
141  * Protocol specific versions
142  */
143
144
145 static void
146 check_buffspace(int msgsize, int buffsize, const char *type __attribute__ ((unused)))
147 {
148   if(msgsize > buffsize)
149     {
150       OLSR_ERROR(LOG_PACKET_CREATION, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
151       olsr_exit(EXIT_FAILURE);
152     }
153 }
154
155 /**
156  *IP version 4
157  *
158  *<b>NO INTERNAL BUFFER</b>
159  *@param ifp use this interfaces address as main address
160  *@return 1 on success
161  */
162
163 static bool
164 serialize_mid4(struct interface *ifp)
165 {
166   uint16_t remainsize, curr_size;
167   /* preserve existing data in output buffer */
168   union olsr_message *m;
169   struct midaddr *addrs;
170   struct interface *ifs;
171
172   if ((olsr_cnf->ip_version != AF_INET) || (!ifp) ||
173       list_is_empty(&interface_head)) {
174     return false;
175   }
176
177   remainsize = net_outbuffer_bytes_left(ifp);
178
179   m = (union olsr_message *)msg_buffer;
180
181   curr_size = OLSR_MID_IPV4_HDRSIZE;
182
183   /* Send pending packet if not room in buffer */
184   if(curr_size > remainsize)
185     {
186       net_output(ifp);
187       remainsize = net_outbuffer_bytes_left(ifp);
188     }
189   check_buffspace(curr_size, remainsize, "MID");
190
191   /* Fill header */
192   m->v4.hopcnt = 0;
193   m->v4.ttl = MAX_TTL;
194   /* Set main(first) address */
195   m->v4.originator = olsr_cnf->router_id.v4.s_addr;
196   m->v4.olsr_msgtype = MID_MESSAGE;
197   m->v4.olsr_vtime = ifp->valtimes.mid;
198
199   addrs = m->v4.message.mid.mid_addr;
200
201   /* Don't add the main address... it's already there */
202   OLSR_FOR_ALL_INTERFACES(ifs) {
203       if(!olsr_ipequal(&olsr_cnf->router_id, &ifs->ip_addr))
204         {
205 #ifdef DEBUG
206           struct ipaddr_str buf;
207 #endif
208
209           if((curr_size + olsr_cnf->ipsize) > remainsize)
210             {
211               /* Only add MID message if it contains data */
212               if(curr_size > OLSR_MID_IPV4_HDRSIZE)
213                 {
214 #ifdef DEBUG
215                   OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
216 #endif
217                   /* set size */
218                   m->v4.olsr_msgsize = htons(curr_size);
219                   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
220
221                   net_outbuffer_push(ifp, msg_buffer, curr_size);
222                   curr_size = OLSR_MID_IPV4_HDRSIZE;
223                   addrs = m->v4.message.mid.mid_addr;
224                 }
225               net_output(ifp);
226               remainsize = net_outbuffer_bytes_left(ifp);
227               check_buffspace(curr_size, remainsize, "MID2");
228             }
229 #ifdef DEBUG
230           OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n",
231                       olsr_ip_to_string(&buf, &ifs->ip_addr),
232                       ifs->int_name);
233 #endif
234
235           addrs->addr = ifs->ip_addr.v4.s_addr;
236           addrs++;
237           curr_size += olsr_cnf->ipsize;
238         }
239   } OLSR_FOR_ALL_INTERFACES_END(ifs);
240
241
242   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
243   m->v4.olsr_msgsize = htons(curr_size);
244
245   //printf("Sending MID (%d bytes)...\n", outputsize);
246   if(curr_size > OLSR_MID_IPV4_HDRSIZE)
247     net_outbuffer_push(ifp, msg_buffer, curr_size);
248
249
250   return true;
251 }
252
253
254
255 /**
256  *IP version 6
257  *
258  *<b>NO INTERNAL BUFFER</b>
259  *@param ifp use this interfaces address as main address
260  *@return 1 on success
261  */
262
263 static bool
264 serialize_mid6(struct interface *ifp)
265 {
266   uint16_t remainsize, curr_size;
267   /* preserve existing data in output buffer */
268   union olsr_message *m;
269   struct midaddr6 *addrs6;
270   struct interface *ifs;
271
272   //printf("\t\tGenerating mid on %s\n", ifn->int_name);
273
274
275   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) ||
276       list_is_empty(&interface_head)) {
277     return false;
278   }
279
280   remainsize = net_outbuffer_bytes_left(ifp);
281
282   curr_size = OLSR_MID_IPV6_HDRSIZE;
283
284   /* Send pending packet if not room in buffer */
285   if(curr_size > remainsize)
286     {
287       net_output(ifp);
288       remainsize = net_outbuffer_bytes_left(ifp);
289     }
290   check_buffspace(curr_size, remainsize, "MID");
291
292   m = (union olsr_message *)msg_buffer;
293
294   /* Build header */
295   m->v6.hopcnt = 0;
296   m->v6.ttl = MAX_TTL;
297   m->v6.olsr_msgtype = MID_MESSAGE;
298   m->v6.olsr_vtime = ifp->valtimes.mid;
299   /* Set main(first) address */
300   m->v6.originator = olsr_cnf->router_id.v6;
301
302   addrs6 = m->v6.message.mid.mid_addr;
303
304   /* Don't add the main address... it's already there */
305   OLSR_FOR_ALL_INTERFACES(ifs) {
306       if(!olsr_ipequal(&olsr_cnf->router_id, &ifs->ip_addr))
307         {
308 #ifdef DEBUG
309           struct ipaddr_str buf;
310 #endif
311           if((curr_size + olsr_cnf->ipsize) > remainsize)
312             {
313               /* Only add MID message if it contains data */
314               if(curr_size > OLSR_MID_IPV6_HDRSIZE)
315                 {
316 #ifdef DEBUG
317                   OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
318 #endif
319                   /* set size */
320                   m->v6.olsr_msgsize = htons(curr_size);
321                   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
322
323                   net_outbuffer_push(ifp, msg_buffer, curr_size);
324                   curr_size = OLSR_MID_IPV6_HDRSIZE;
325                   addrs6 = m->v6.message.mid.mid_addr;
326                 }
327               net_output(ifp);
328               remainsize = net_outbuffer_bytes_left(ifp);
329               check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
330             }
331 #ifdef DEBUG
332                   OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n",
333                               olsr_ip_to_string(&buf, &ifs->ip_addr),
334                               ifs->int_name);
335 #endif
336
337           addrs6->addr = ifs->ip_addr.v6;
338           addrs6++;
339           curr_size += olsr_cnf->ipsize;
340         }
341   } OLSR_FOR_ALL_INTERFACES_END(ifs);
342
343   m->v6.olsr_msgsize = htons(curr_size);
344   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
345
346   //printf("Sending MID (%d bytes)...\n", outputsize);
347   if(curr_size > OLSR_MID_IPV6_HDRSIZE)
348     net_outbuffer_push(ifp, msg_buffer, curr_size);
349
350   return true;
351 }
352
353
354
355
356 /**
357  *IP version 4
358  *
359  *@param ifp the interface to send on
360  *@return nada
361  */
362 static bool
363 serialize_hna4(struct interface *ifp)
364 {
365   uint16_t remainsize, curr_size;
366   /* preserve existing data in output buffer */
367   union olsr_message *m;
368   struct hnapair *pair;
369   struct ip_prefix_entry *h;
370
371   /* No hna nets */
372   if (ifp == NULL) {
373     return false;
374   }
375   if (olsr_cnf->ip_version != AF_INET) {
376     return false;
377   }
378   if (list_is_empty(&olsr_cnf->hna_entries)) {
379     return false;
380   }
381
382   remainsize = net_outbuffer_bytes_left(ifp);
383
384   curr_size = OLSR_HNA_IPV4_HDRSIZE;
385
386   /* Send pending packet if not room in buffer */
387   if(curr_size > remainsize)
388     {
389       net_output(ifp);
390       remainsize = net_outbuffer_bytes_left(ifp);
391     }
392   check_buffspace(curr_size, remainsize, "HNA");
393
394   m = (union olsr_message *)msg_buffer;
395
396
397   /* Fill header */
398   m->v4.originator = olsr_cnf->router_id.v4.s_addr;
399   m->v4.hopcnt = 0;
400   m->v4.ttl = MAX_TTL;
401   m->v4.olsr_msgtype = HNA_MESSAGE;
402   m->v4.olsr_vtime = ifp->valtimes.hna;
403
404
405   pair = m->v4.message.hna.hna_net;
406
407   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
408 #ifdef DEBUG
409       struct ipprefix_str prefixstr;
410 #endif
411       union olsr_ip_addr ip_addr;
412       if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
413         {
414           /* Only add HNA message if it contains data */
415           if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
416             {
417 #ifdef DEBUG
418               OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
419 #endif
420               m->v4.seqno = htons(get_msg_seqno());
421               m->v4.olsr_msgsize = htons(curr_size);
422               net_outbuffer_push(ifp, msg_buffer, curr_size);
423               curr_size = OLSR_HNA_IPV4_HDRSIZE;
424               pair = m->v4.message.hna.hna_net;
425             }
426           net_output(ifp);
427           remainsize = net_outbuffer_bytes_left(ifp);
428           check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
429         }
430 #ifdef DEBUG
431       OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
432 #endif
433       pair->addr = h->net.prefix.v4.s_addr;
434       olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
435       pair->netmask = ip_addr.v4.s_addr;
436       pair++;
437       curr_size += (2 * olsr_cnf->ipsize);
438   } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
439
440   m->v4.seqno = htons(get_msg_seqno());
441   m->v4.olsr_msgsize = htons(curr_size);
442
443   net_outbuffer_push(ifp, msg_buffer, curr_size);
444
445   //printf("Sending HNA (%d bytes)...\n", outputsize);
446   return false;
447 }
448
449
450 /**
451  *IP version 6
452  *
453  *@param ifp the interface to send on
454  *@return nada
455  */
456 static bool
457 serialize_hna6(struct interface *ifp)
458 {
459   uint16_t remainsize, curr_size;
460   /* preserve existing data in output buffer */
461   union olsr_message *m;
462   struct hnapair6 *pair6;
463   union olsr_ip_addr tmp_netmask;
464   struct ip_prefix_entry *h;
465
466   /* No hna nets */
467   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || list_is_empty(&olsr_cnf->hna_entries))
468     return false;
469
470
471   remainsize = net_outbuffer_bytes_left(ifp);
472
473   curr_size = OLSR_HNA_IPV6_HDRSIZE;
474
475   /* Send pending packet if not room in buffer */
476   if(curr_size > remainsize)
477     {
478       net_output(ifp);
479       remainsize = net_outbuffer_bytes_left(ifp);
480     }
481   check_buffspace(curr_size, remainsize, "HNA");
482
483   m = (union olsr_message *)msg_buffer;
484
485   /* Fill header */
486   m->v6.originator = olsr_cnf->router_id.v6;
487   m->v6.hopcnt = 0;
488   m->v6.ttl = MAX_TTL;
489   m->v6.olsr_msgtype = HNA_MESSAGE;
490   m->v6.olsr_vtime = ifp->valtimes.hna;
491
492   pair6 = m->v6.message.hna.hna_net;
493
494
495   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
496 #ifdef DEBUG
497       struct ipprefix_str prefixstr;
498 #endif
499       if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
500         {
501           /* Only add HNA message if it contains data */
502           if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
503             {
504 #ifdef DEBUG
505               OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
506 #endif
507               m->v6.seqno = htons(get_msg_seqno());
508               m->v6.olsr_msgsize = htons(curr_size);
509               net_outbuffer_push(ifp, msg_buffer, curr_size);
510               curr_size = OLSR_HNA_IPV6_HDRSIZE;
511               pair6 = m->v6.message.hna.hna_net;
512             }
513           net_output(ifp);
514           remainsize = net_outbuffer_bytes_left(ifp);
515           check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
516         }
517 #ifdef DEBUG
518       OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
519 #endif
520       pair6->addr = h->net.prefix.v6;
521       olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
522       pair6->netmask = tmp_netmask.v6;
523       pair6++;
524       curr_size += (2 * olsr_cnf->ipsize);
525     } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
526
527   m->v6.olsr_msgsize = htons(curr_size);
528   m->v6.seqno = htons(get_msg_seqno());
529
530   net_outbuffer_push(ifp, msg_buffer, curr_size);
531 #if 0
532   printf("Sending HNA (%d bytes)...\n", outputsize);
533 #endif
534   return false;
535
536 }
537
538 /*
539  * Local Variables:
540  * c-basic-offset: 2
541  * indent-tabs-mode: nil
542  * End:
543  */