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"
51 #define OLSR_IPV4_HDRSIZE 12
52 #define OLSR_IPV6_HDRSIZE 24
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
64 check_buffspace(int msgsize, int buffsize, const char *type);
66 /* All these functions share this buffer */
68 static uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
70 /* Prototypes for internal functions */
75 serialize_mid4(struct interface *);
78 serialize_hna4(struct interface *);
83 serialize_mid6(struct interface *);
86 serialize_hna6(struct interface *);
89 *Build a MID message to the outputbuffer
91 *<b>NO INTERNAL BUFFER</b>
92 *@param ifn use this interfaces address as main address
97 queue_mid(struct interface *ifp)
99 OLSR_INFO(LOG_PACKET_CREATION, "Building MID on %s\n-------------------\n", ifp->int_name);
101 switch(olsr_cnf->ip_version)
104 return serialize_mid4(ifp);
106 return serialize_mid6(ifp);
113 *Builds a HNA message in the outputbuffer
114 *<b>NB! Not internal packetformat!</b>
116 *@param ifp the interface to send on
120 queue_hna(struct interface *ifp)
122 OLSR_INFO(LOG_PACKET_CREATION, "Building HNA on %s\n-------------------\n", ifp->int_name);
124 switch(olsr_cnf->ip_version)
127 return serialize_hna4(ifp);
129 return serialize_hna6(ifp);
135 * Protocol specific versions
140 check_buffspace(int msgsize, int buffsize, const char *type __attribute__ ((unused)))
142 if(msgsize > buffsize)
144 OLSR_ERROR(LOG_PACKET_CREATION, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
145 olsr_exit(EXIT_FAILURE);
152 *<b>NO INTERNAL BUFFER</b>
153 *@param ifp use this interfaces address as main address
154 *@return 1 on success
158 serialize_mid4(struct interface *ifp)
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;
168 if ((olsr_cnf->ip_version != AF_INET) || (!ifp) ||
169 list_is_empty(&interface_head)) {
173 remainsize = net_outbuffer_bytes_left(ifp);
175 m = (union olsr_message *)msg_buffer;
177 curr_size = OLSR_MID_IPV4_HDRSIZE;
179 /* Send pending packet if not room in buffer */
180 if(curr_size > remainsize)
183 remainsize = net_outbuffer_bytes_left(ifp);
185 check_buffspace(curr_size, remainsize, "MID");
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;
195 addrs = m->v4.message.mid.mid_addr;
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))
201 if((curr_size + olsr_cnf->ipsize) > remainsize)
203 /* Only add MID message if it contains data */
204 if(curr_size > OLSR_MID_IPV4_HDRSIZE)
206 OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
208 m->v4.olsr_msgsize = htons(curr_size);
209 m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
211 net_outbuffer_push(ifp, msg_buffer, curr_size);
212 curr_size = OLSR_MID_IPV4_HDRSIZE;
213 addrs = m->v4.message.mid.mid_addr;
216 remainsize = net_outbuffer_bytes_left(ifp);
217 check_buffspace(curr_size, remainsize, "MID2");
219 OLSR_DEBUG(LOG_PACKET_CREATION, "\t%s(%s)\n",
220 olsr_ip_to_string(&buf, &ifs->ip_addr),
223 addrs->addr = ifs->ip_addr.v4.s_addr;
225 curr_size += olsr_cnf->ipsize;
227 } OLSR_FOR_ALL_INTERFACES_END(ifs);
230 m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
231 m->v4.olsr_msgsize = htons(curr_size);
233 if(curr_size > OLSR_MID_IPV4_HDRSIZE)
234 net_outbuffer_push(ifp, msg_buffer, curr_size);
244 *<b>NO INTERNAL BUFFER</b>
245 *@param ifp use this interfaces address as main address
246 *@return 1 on success
250 serialize_mid6(struct interface *ifp)
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;
261 if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) ||
262 list_is_empty(&interface_head)) {
266 remainsize = net_outbuffer_bytes_left(ifp);
268 curr_size = OLSR_MID_IPV6_HDRSIZE;
270 /* Send pending packet if not room in buffer */
271 if(curr_size > remainsize)
274 remainsize = net_outbuffer_bytes_left(ifp);
276 check_buffspace(curr_size, remainsize, "MID");
278 m = (union olsr_message *)msg_buffer;
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;
288 addrs6 = m->v6.message.mid.mid_addr;
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))
294 if((curr_size + olsr_cnf->ipsize) > remainsize)
296 /* Only add MID message if it contains data */
297 if(curr_size > OLSR_MID_IPV6_HDRSIZE)
299 OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
301 m->v6.olsr_msgsize = htons(curr_size);
302 m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
304 net_outbuffer_push(ifp, msg_buffer, curr_size);
305 curr_size = OLSR_MID_IPV6_HDRSIZE;
306 addrs6 = m->v6.message.mid.mid_addr;
309 remainsize = net_outbuffer_bytes_left(ifp);
310 check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
312 OLSR_DEBUG(LOG_PACKET_CREATION, "\t%s(%s)\n",
313 olsr_ip_to_string(&buf, &ifs->ip_addr),
316 addrs6->addr = ifs->ip_addr.v6;
318 curr_size += olsr_cnf->ipsize;
320 } OLSR_FOR_ALL_INTERFACES_END(ifs);
322 m->v6.olsr_msgsize = htons(curr_size);
323 m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
325 if(curr_size > OLSR_MID_IPV6_HDRSIZE)
326 net_outbuffer_push(ifp, msg_buffer, curr_size);
337 *@param ifp the interface to send on
341 serialize_hna4(struct interface *ifp)
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;
355 if (olsr_cnf->ip_version != AF_INET) {
358 if (list_is_empty(&olsr_cnf->hna_entries)) {
362 remainsize = net_outbuffer_bytes_left(ifp);
364 curr_size = OLSR_HNA_IPV4_HDRSIZE;
366 /* Send pending packet if not room in buffer */
367 if(curr_size > remainsize)
370 remainsize = net_outbuffer_bytes_left(ifp);
372 check_buffspace(curr_size, remainsize, "HNA");
374 m = (union olsr_message *)msg_buffer;
378 m->v4.originator = olsr_cnf->router_id.v4.s_addr;
381 m->v4.olsr_msgtype = HNA_MESSAGE;
382 m->v4.olsr_vtime = ifp->valtimes.hna;
385 pair = m->v4.message.hna.hna_net;
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)
391 /* Only add HNA message if it contains data */
392 if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
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;
402 remainsize = net_outbuffer_bytes_left(ifp);
403 check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
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;
410 curr_size += (2 * olsr_cnf->ipsize);
411 } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
413 m->v4.seqno = htons(get_msg_seqno());
414 m->v4.olsr_msgsize = htons(curr_size);
416 net_outbuffer_push(ifp, msg_buffer, curr_size);
425 *@param ifp the interface to send on
429 serialize_hna6(struct interface *ifp)
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;
442 if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || list_is_empty(&olsr_cnf->hna_entries))
446 remainsize = net_outbuffer_bytes_left(ifp);
448 curr_size = OLSR_HNA_IPV6_HDRSIZE;
450 /* Send pending packet if not room in buffer */
451 if(curr_size > remainsize)
454 remainsize = net_outbuffer_bytes_left(ifp);
456 check_buffspace(curr_size, remainsize, "HNA");
458 m = (union olsr_message *)msg_buffer;
461 m->v6.originator = olsr_cnf->router_id.v6;
464 m->v6.olsr_msgtype = HNA_MESSAGE;
465 m->v6.olsr_vtime = ifp->valtimes.hna;
467 pair6 = m->v6.message.hna.hna_net;
470 OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
471 if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
473 /* Only add HNA message if it contains data */
474 if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
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;
484 remainsize = net_outbuffer_bytes_left(ifp);
485 check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
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;
492 curr_size += (2 * olsr_cnf->ipsize);
493 } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
495 m->v6.olsr_msgsize = htons(curr_size);
496 m->v6.seqno = htons(get_msg_seqno());
498 net_outbuffer_push(ifp, msg_buffer, curr_size);
505 * indent-tabs-mode: nil