2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
41 #include "build_msg.h"
47 #include "olsr_ip_prefix_list.h"
53 #define OLSR_IPV4_HDRSIZE 12
54 #define OLSR_IPV6_HDRSIZE 24
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
66 check_buffspace(int msgsize, int buffsize, const char *type);
68 /* All these functions share this buffer */
70 static uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
72 /* Prototypes for internal functions */
77 serialize_mid4(struct interface *);
80 serialize_hna4(struct interface *);
85 serialize_mid6(struct interface *);
88 serialize_hna6(struct interface *);
91 *Build a MID message to the outputbuffer
93 *<b>NO INTERNAL BUFFER</b>
94 *@param ifn use this interfaces address as main address
99 queue_mid(struct interface *ifp)
102 OLSR_PRINTF(BMSG_DBGLVL, "Building MID on %s\n-------------------\n", ifp->int_name);
105 switch(olsr_cnf->ip_version)
108 return serialize_mid4(ifp);
110 return serialize_mid6(ifp);
117 *Builds a HNA message in the outputbuffer
118 *<b>NB! Not internal packetformat!</b>
120 *@param ifp the interface to send on
124 queue_hna(struct interface *ifp)
127 OLSR_PRINTF(BMSG_DBGLVL, "Building HNA on %s\n-------------------\n", ifp->int_name);
130 switch(olsr_cnf->ip_version)
133 return serialize_hna4(ifp);
135 return serialize_hna6(ifp);
141 * Protocol specific versions
146 check_buffspace(int msgsize, int buffsize, const char *type __attribute__ ((unused)))
148 if(msgsize > buffsize)
150 OLSR_ERROR(LOG_PACKET_CREATION, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
151 olsr_exit(EXIT_FAILURE);
158 *<b>NO INTERNAL BUFFER</b>
159 *@param ifp use this interfaces address as main address
160 *@return 1 on success
164 serialize_mid4(struct interface *ifp)
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;
172 if ((olsr_cnf->ip_version != AF_INET) || (!ifp) ||
173 list_is_empty(&interface_head)) {
177 remainsize = net_outbuffer_bytes_left(ifp);
179 m = (union olsr_message *)msg_buffer;
181 curr_size = OLSR_MID_IPV4_HDRSIZE;
183 /* Send pending packet if not room in buffer */
184 if(curr_size > remainsize)
187 remainsize = net_outbuffer_bytes_left(ifp);
189 check_buffspace(curr_size, remainsize, "MID");
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;
199 addrs = m->v4.message.mid.mid_addr;
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))
206 struct ipaddr_str buf;
209 if((curr_size + olsr_cnf->ipsize) > remainsize)
211 /* Only add MID message if it contains data */
212 if(curr_size > OLSR_MID_IPV4_HDRSIZE)
215 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
218 m->v4.olsr_msgsize = htons(curr_size);
219 m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
221 net_outbuffer_push(ifp, msg_buffer, curr_size);
222 curr_size = OLSR_MID_IPV4_HDRSIZE;
223 addrs = m->v4.message.mid.mid_addr;
226 remainsize = net_outbuffer_bytes_left(ifp);
227 check_buffspace(curr_size, remainsize, "MID2");
230 OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n",
231 olsr_ip_to_string(&buf, &ifs->ip_addr),
235 addrs->addr = ifs->ip_addr.v4.s_addr;
237 curr_size += olsr_cnf->ipsize;
239 } OLSR_FOR_ALL_INTERFACES_END(ifs);
242 m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
243 m->v4.olsr_msgsize = htons(curr_size);
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);
258 *<b>NO INTERNAL BUFFER</b>
259 *@param ifp use this interfaces address as main address
260 *@return 1 on success
264 serialize_mid6(struct interface *ifp)
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;
272 //printf("\t\tGenerating mid on %s\n", ifn->int_name);
275 if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) ||
276 list_is_empty(&interface_head)) {
280 remainsize = net_outbuffer_bytes_left(ifp);
282 curr_size = OLSR_MID_IPV6_HDRSIZE;
284 /* Send pending packet if not room in buffer */
285 if(curr_size > remainsize)
288 remainsize = net_outbuffer_bytes_left(ifp);
290 check_buffspace(curr_size, remainsize, "MID");
292 m = (union olsr_message *)msg_buffer;
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;
302 addrs6 = m->v6.message.mid.mid_addr;
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))
309 struct ipaddr_str buf;
311 if((curr_size + olsr_cnf->ipsize) > remainsize)
313 /* Only add MID message if it contains data */
314 if(curr_size > OLSR_MID_IPV6_HDRSIZE)
317 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
320 m->v6.olsr_msgsize = htons(curr_size);
321 m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
323 net_outbuffer_push(ifp, msg_buffer, curr_size);
324 curr_size = OLSR_MID_IPV6_HDRSIZE;
325 addrs6 = m->v6.message.mid.mid_addr;
328 remainsize = net_outbuffer_bytes_left(ifp);
329 check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
332 OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n",
333 olsr_ip_to_string(&buf, &ifs->ip_addr),
337 addrs6->addr = ifs->ip_addr.v6;
339 curr_size += olsr_cnf->ipsize;
341 } OLSR_FOR_ALL_INTERFACES_END(ifs);
343 m->v6.olsr_msgsize = htons(curr_size);
344 m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
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);
359 *@param ifp the interface to send on
363 serialize_hna4(struct interface *ifp)
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;
375 if (olsr_cnf->ip_version != AF_INET) {
378 if (list_is_empty(&olsr_cnf->hna_entries)) {
382 remainsize = net_outbuffer_bytes_left(ifp);
384 curr_size = OLSR_HNA_IPV4_HDRSIZE;
386 /* Send pending packet if not room in buffer */
387 if(curr_size > remainsize)
390 remainsize = net_outbuffer_bytes_left(ifp);
392 check_buffspace(curr_size, remainsize, "HNA");
394 m = (union olsr_message *)msg_buffer;
398 m->v4.originator = olsr_cnf->router_id.v4.s_addr;
401 m->v4.olsr_msgtype = HNA_MESSAGE;
402 m->v4.olsr_vtime = ifp->valtimes.hna;
405 pair = m->v4.message.hna.hna_net;
407 OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
409 struct ipprefix_str prefixstr;
411 union olsr_ip_addr ip_addr;
412 if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
414 /* Only add HNA message if it contains data */
415 if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
418 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
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;
427 remainsize = net_outbuffer_bytes_left(ifp);
428 check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
431 OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
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;
437 curr_size += (2 * olsr_cnf->ipsize);
438 } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
440 m->v4.seqno = htons(get_msg_seqno());
441 m->v4.olsr_msgsize = htons(curr_size);
443 net_outbuffer_push(ifp, msg_buffer, curr_size);
445 //printf("Sending HNA (%d bytes)...\n", outputsize);
453 *@param ifp the interface to send on
457 serialize_hna6(struct interface *ifp)
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;
467 if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || list_is_empty(&olsr_cnf->hna_entries))
471 remainsize = net_outbuffer_bytes_left(ifp);
473 curr_size = OLSR_HNA_IPV6_HDRSIZE;
475 /* Send pending packet if not room in buffer */
476 if(curr_size > remainsize)
479 remainsize = net_outbuffer_bytes_left(ifp);
481 check_buffspace(curr_size, remainsize, "HNA");
483 m = (union olsr_message *)msg_buffer;
486 m->v6.originator = olsr_cnf->router_id.v6;
489 m->v6.olsr_msgtype = HNA_MESSAGE;
490 m->v6.olsr_vtime = ifp->valtimes.hna;
492 pair6 = m->v6.message.hna.hna_net;
495 OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
497 struct ipprefix_str prefixstr;
499 if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
501 /* Only add HNA message if it contains data */
502 if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
505 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
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;
514 remainsize = net_outbuffer_bytes_left(ifp);
515 check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
518 OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
520 pair6->addr = h->net.prefix.v6;
521 olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
522 pair6->netmask = tmp_netmask.v6;
524 curr_size += (2 * olsr_cnf->ipsize);
525 } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
527 m->v6.olsr_msgsize = htons(curr_size);
528 m->v6.seqno = htons(get_msg_seqno());
530 net_outbuffer_push(ifp, msg_buffer, curr_size);
532 printf("Sending HNA (%d bytes)...\n", outputsize);
541 * indent-tabs-mode: nil