convert ip_prefix_list to common/list datastructure
[olsrd.git] / src / build_msg.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
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)
147 {
148   if(msgsize > buffsize)
149     {
150       OLSR_PRINTF(1, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
151       olsr_syslog(OLSR_LOG_ERR, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
152       olsr_exit(__func__, EXIT_FAILURE);
153     }
154 }
155
156 /**
157  *IP version 4
158  *
159  *<b>NO INTERNAL BUFFER</b>
160  *@param ifp use this interfaces address as main address
161  *@return 1 on success
162  */
163
164 static bool
165 serialize_mid4(struct interface *ifp)
166 {
167   uint16_t remainsize, curr_size;
168   /* preserve existing data in output buffer */
169   union olsr_message *m;
170   struct midaddr *addrs;
171   struct interface *ifs;
172
173   if ((olsr_cnf->ip_version != AF_INET) || (!ifp) ||
174       list_is_empty(&interface_head)) {
175     return false;
176   }
177
178   remainsize = net_outbuffer_bytes_left(ifp);
179
180   m = (union olsr_message *)msg_buffer;
181
182   curr_size = OLSR_MID_IPV4_HDRSIZE;
183
184   /* Send pending packet if not room in buffer */
185   if(curr_size > remainsize)
186     {
187       net_output(ifp);
188       remainsize = net_outbuffer_bytes_left(ifp);
189     }
190   check_buffspace(curr_size, remainsize, "MID");
191
192   /* Fill header */
193   m->v4.hopcnt = 0;
194   m->v4.ttl = MAX_TTL;
195   /* Set main(first) address */
196   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
197   m->v4.olsr_msgtype = MID_MESSAGE;
198   m->v4.olsr_vtime = ifp->valtimes.mid;
199
200   addrs = m->v4.message.mid.mid_addr;
201
202   /* Don't add the main address... it's already there */
203   OLSR_FOR_ALL_INTERFACES(ifs) {
204       if(!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr))
205         {
206 #ifdef DEBUG
207           struct ipaddr_str buf;
208 #endif
209
210           if((curr_size + olsr_cnf->ipsize) > remainsize)
211             {
212               /* Only add MID message if it contains data */
213               if(curr_size > OLSR_MID_IPV4_HDRSIZE)
214                 {
215 #ifdef DEBUG
216                   OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
217 #endif
218                   /* set size */
219                   m->v4.olsr_msgsize = htons(curr_size);
220                   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
221
222                   net_outbuffer_push(ifp, msg_buffer, curr_size);
223                   curr_size = OLSR_MID_IPV4_HDRSIZE;
224                   addrs = m->v4.message.mid.mid_addr;
225                 }
226               net_output(ifp);
227               remainsize = net_outbuffer_bytes_left(ifp);
228               check_buffspace(curr_size, remainsize, "MID2");
229             }
230 #ifdef DEBUG
231           OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n",
232                       olsr_ip_to_string(&buf, &ifs->ip_addr),
233                       ifs->int_name);
234 #endif
235
236           addrs->addr = ifs->ip_addr.v4.s_addr;
237           addrs++;
238           curr_size += olsr_cnf->ipsize;
239         }
240   } OLSR_FOR_ALL_INTERFACES_END(ifs);
241
242
243   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
244   m->v4.olsr_msgsize = htons(curr_size);
245
246   //printf("Sending MID (%d bytes)...\n", outputsize);
247   if(curr_size > OLSR_MID_IPV4_HDRSIZE)
248     net_outbuffer_push(ifp, msg_buffer, curr_size);
249
250
251   return true;
252 }
253
254
255
256 /**
257  *IP version 6
258  *
259  *<b>NO INTERNAL BUFFER</b>
260  *@param ifp use this interfaces address as main address
261  *@return 1 on success
262  */
263
264 static bool
265 serialize_mid6(struct interface *ifp)
266 {
267   uint16_t remainsize, curr_size;
268   /* preserve existing data in output buffer */
269   union olsr_message *m;
270   struct midaddr6 *addrs6;
271   struct interface *ifs;
272
273   //printf("\t\tGenerating mid on %s\n", ifn->int_name);
274
275
276   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) ||
277       list_is_empty(&interface_head)) {
278     return false;
279   }
280
281   remainsize = net_outbuffer_bytes_left(ifp);
282
283   curr_size = OLSR_MID_IPV6_HDRSIZE;
284
285   /* Send pending packet if not room in buffer */
286   if(curr_size > remainsize)
287     {
288       net_output(ifp);
289       remainsize = net_outbuffer_bytes_left(ifp);
290     }
291   check_buffspace(curr_size, remainsize, "MID");
292
293   m = (union olsr_message *)msg_buffer;
294
295   /* Build header */
296   m->v6.hopcnt = 0;
297   m->v6.ttl = MAX_TTL;
298   m->v6.olsr_msgtype = MID_MESSAGE;
299   m->v6.olsr_vtime = ifp->valtimes.mid;
300   /* Set main(first) address */
301   m->v6.originator = olsr_cnf->main_addr.v6;
302
303   addrs6 = m->v6.message.mid.mid_addr;
304
305   /* Don't add the main address... it's already there */
306   OLSR_FOR_ALL_INTERFACES(ifs) {
307       if(!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr))
308         {
309 #ifdef DEBUG
310           struct ipaddr_str buf;
311 #endif
312           if((curr_size + olsr_cnf->ipsize) > remainsize)
313             {
314               /* Only add MID message if it contains data */
315               if(curr_size > OLSR_MID_IPV6_HDRSIZE)
316                 {
317 #ifdef DEBUG
318                   OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
319 #endif
320                   /* set size */
321                   m->v6.olsr_msgsize = htons(curr_size);
322                   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
323
324                   net_outbuffer_push(ifp, msg_buffer, curr_size);
325                   curr_size = OLSR_MID_IPV6_HDRSIZE;
326                   addrs6 = m->v6.message.mid.mid_addr;
327                 }
328               net_output(ifp);
329               remainsize = net_outbuffer_bytes_left(ifp);
330               check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
331             }
332 #ifdef DEBUG
333                   OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n",
334                               olsr_ip_to_string(&buf, &ifs->ip_addr),
335                               ifs->int_name);
336 #endif
337
338           addrs6->addr = ifs->ip_addr.v6;
339           addrs6++;
340           curr_size += olsr_cnf->ipsize;
341         }
342   } OLSR_FOR_ALL_INTERFACES_END(ifs);
343
344   m->v6.olsr_msgsize = htons(curr_size);
345   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
346
347   //printf("Sending MID (%d bytes)...\n", outputsize);
348   if(curr_size > OLSR_MID_IPV6_HDRSIZE)
349     net_outbuffer_push(ifp, msg_buffer, curr_size);
350
351   return true;
352 }
353
354
355
356
357 /**
358  *IP version 4
359  *
360  *@param ifp the interface to send on
361  *@return nada
362  */
363 static bool
364 serialize_hna4(struct interface *ifp)
365 {
366   uint16_t remainsize, curr_size;
367   /* preserve existing data in output buffer */
368   union olsr_message *m;
369   struct hnapair *pair;
370   struct ip_prefix_entry *h;
371
372   /* No hna nets */
373   if (ifp == NULL) {
374     return false;
375   }
376   if (olsr_cnf->ip_version != AF_INET) {
377     return false;
378   }
379   if (list_is_empty(&olsr_cnf->hna_entries)) {
380     return false;
381   }
382
383   remainsize = net_outbuffer_bytes_left(ifp);
384
385   curr_size = OLSR_HNA_IPV4_HDRSIZE;
386
387   /* Send pending packet if not room in buffer */
388   if(curr_size > remainsize)
389     {
390       net_output(ifp);
391       remainsize = net_outbuffer_bytes_left(ifp);
392     }
393   check_buffspace(curr_size, remainsize, "HNA");
394
395   m = (union olsr_message *)msg_buffer;
396
397
398   /* Fill header */
399   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
400   m->v4.hopcnt = 0;
401   m->v4.ttl = MAX_TTL;
402   m->v4.olsr_msgtype = HNA_MESSAGE;
403   m->v4.olsr_vtime = ifp->valtimes.hna;
404
405
406   pair = m->v4.message.hna.hna_net;
407
408   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
409 #ifdef DEBUG
410       struct ipprefix_str prefixstr;
411 #endif
412       union olsr_ip_addr ip_addr;
413       if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
414         {
415           /* Only add HNA message if it contains data */
416           if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
417             {
418 #ifdef DEBUG
419               OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
420 #endif
421               m->v4.seqno = htons(get_msg_seqno());
422               m->v4.olsr_msgsize = htons(curr_size);
423               net_outbuffer_push(ifp, msg_buffer, curr_size);
424               curr_size = OLSR_HNA_IPV4_HDRSIZE;
425               pair = m->v4.message.hna.hna_net;
426             }
427           net_output(ifp);
428           remainsize = net_outbuffer_bytes_left(ifp);
429           check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
430         }
431 #ifdef DEBUG
432       OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
433 #endif
434       pair->addr = h->net.prefix.v4.s_addr;
435       olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
436       pair->netmask = ip_addr.v4.s_addr;
437       pair++;
438       curr_size += (2 * olsr_cnf->ipsize);
439   } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
440
441   m->v4.seqno = htons(get_msg_seqno());
442   m->v4.olsr_msgsize = htons(curr_size);
443
444   net_outbuffer_push(ifp, msg_buffer, curr_size);
445
446   //printf("Sending HNA (%d bytes)...\n", outputsize);
447   return false;
448 }
449
450
451 /**
452  *IP version 6
453  *
454  *@param ifp the interface to send on
455  *@return nada
456  */
457 static bool
458 serialize_hna6(struct interface *ifp)
459 {
460   uint16_t remainsize, curr_size;
461   /* preserve existing data in output buffer */
462   union olsr_message *m;
463   struct hnapair6 *pair6;
464   union olsr_ip_addr tmp_netmask;
465   struct ip_prefix_entry *h;
466
467   /* No hna nets */
468   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || list_is_empty(&olsr_cnf->hna_entries))
469     return false;
470
471
472   remainsize = net_outbuffer_bytes_left(ifp);
473
474   curr_size = OLSR_HNA_IPV6_HDRSIZE;
475
476   /* Send pending packet if not room in buffer */
477   if(curr_size > remainsize)
478     {
479       net_output(ifp);
480       remainsize = net_outbuffer_bytes_left(ifp);
481     }
482   check_buffspace(curr_size, remainsize, "HNA");
483
484   m = (union olsr_message *)msg_buffer;
485
486   /* Fill header */
487   m->v6.originator = olsr_cnf->main_addr.v6;
488   m->v6.hopcnt = 0;
489   m->v6.ttl = MAX_TTL;
490   m->v6.olsr_msgtype = HNA_MESSAGE;
491   m->v6.olsr_vtime = ifp->valtimes.hna;
492
493   pair6 = m->v6.message.hna.hna_net;
494
495
496   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
497 #ifdef DEBUG
498       struct ipprefix_str prefixstr;
499 #endif
500       if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
501         {
502           /* Only add HNA message if it contains data */
503           if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
504             {
505 #ifdef DEBUG
506               OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
507 #endif
508               m->v6.seqno = htons(get_msg_seqno());
509               m->v6.olsr_msgsize = htons(curr_size);
510               net_outbuffer_push(ifp, msg_buffer, curr_size);
511               curr_size = OLSR_HNA_IPV6_HDRSIZE;
512               pair6 = m->v6.message.hna.hna_net;
513             }
514           net_output(ifp);
515           remainsize = net_outbuffer_bytes_left(ifp);
516           check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
517         }
518 #ifdef DEBUG
519       OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
520 #endif
521       pair6->addr = h->net.prefix.v6;
522       olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
523       pair6->netmask = tmp_netmask.v6;
524       pair6++;
525       curr_size += (2 * olsr_cnf->ipsize);
526     } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
527
528   m->v6.olsr_msgsize = htons(curr_size);
529   m->v6.seqno = htons(get_msg_seqno());
530
531   net_outbuffer_push(ifp, msg_buffer, curr_size);
532 #if 0
533   printf("Sending HNA (%d bytes)...\n", outputsize);
534 #endif
535   return false;
536
537 }
538
539 /*
540  * Local Variables:
541  * c-basic-offset: 2
542  * indent-tabs-mode: nil
543  * End:
544  */