Unify MID generation and put it into mid_set.c
[olsrd.git] / src / build_msg.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "build_msg.h"
43 #include "ipcalc.h"
44 #include "olsr.h"
45 #include "log.h"
46 #include "olsr_time.h"
47 #include "net_olsr.h"
48 #include "olsr_ip_prefix_list.h"
49
50 #include <stdlib.h>
51
52 #define OLSR_IPV4_HDRSIZE          12
53 #define OLSR_IPV6_HDRSIZE          24
54
55 #define OLSR_HELLO_IPV4_HDRSIZE    (OLSR_IPV4_HDRSIZE + 4)
56 #define OLSR_HELLO_IPV6_HDRSIZE    (OLSR_IPV6_HDRSIZE + 4)
57 #define OLSR_TC_IPV4_HDRSIZE       (OLSR_IPV4_HDRSIZE + 4)
58 #define OLSR_TC_IPV6_HDRSIZE       (OLSR_IPV6_HDRSIZE + 4)
59 #define OLSR_MID_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
60 #define OLSR_MID_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
61 #define OLSR_HNA_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
62 #define OLSR_HNA_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
63
64 static void
65   check_buffspace(int msgsize, int buffsize, const char *type);
66
67 /* All these functions share this buffer */
68
69 static uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
70
71 /* Prototypes for internal functions */
72
73 /* IPv4 */
74
75 static bool serialize_hna4(struct interface *);
76
77 /* IPv6 */
78
79 static bool serialize_hna6(struct interface *);
80
81 /**
82  *Builds a HNA message in the outputbuffer
83  *<b>NB! Not internal packetformat!</b>
84  *
85  *@param ifp the interface to send on
86  *@return nada
87  */
88 bool
89 queue_hna(struct interface * ifp)
90 {
91   OLSR_INFO(LOG_PACKET_CREATION, "Building HNA on %s\n-------------------\n", ifp->int_name);
92
93   switch (olsr_cnf->ip_version) {
94   case (AF_INET):
95     return serialize_hna4(ifp);
96   case (AF_INET6):
97     return serialize_hna6(ifp);
98   }
99   return false;
100 }
101
102 /*
103  * Protocol specific versions
104  */
105
106
107 static void
108 check_buffspace(int msgsize, int buffsize, const char *type __attribute__ ((unused)))
109 {
110   if (msgsize > buffsize) {
111     OLSR_ERROR(LOG_PACKET_CREATION, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize);
112     olsr_exit(EXIT_FAILURE);
113   }
114 }
115
116 /**
117  *IP version 4
118  *
119  *@param ifp the interface to send on
120  *@return nada
121  */
122 static bool
123 serialize_hna4(struct interface *ifp)
124 {
125   uint16_t remainsize, curr_size;
126   /* preserve existing data in output buffer */
127   union olsr_message *m;
128   struct hnapair *pair;
129   struct ip_prefix_entry *h;
130 #if !defined REMOVE_LOG_DEBUG
131   struct ipprefix_str prefixstr;
132 #endif
133   /* No hna nets */
134   if (ifp == NULL) {
135     return false;
136   }
137   if (olsr_cnf->ip_version != AF_INET) {
138     return false;
139   }
140   if (list_is_empty(&olsr_cnf->hna_entries)) {
141     return false;
142   }
143
144   remainsize = net_outbuffer_bytes_left(ifp);
145
146   curr_size = OLSR_HNA_IPV4_HDRSIZE;
147
148   /* Send pending packet if not room in buffer */
149   if (curr_size > remainsize) {
150     net_output(ifp);
151     remainsize = net_outbuffer_bytes_left(ifp);
152   }
153   check_buffspace(curr_size, remainsize, "HNA");
154
155   m = (union olsr_message *)msg_buffer;
156
157
158   /* Fill header */
159   m->v4.originator = olsr_cnf->router_id.v4.s_addr;
160   m->v4.hopcnt = 0;
161   m->v4.ttl = MAX_TTL;
162   m->v4.olsr_msgtype = HNA_MESSAGE;
163   m->v4.olsr_vtime = reltime_to_me(olsr_cnf->hna_params.validity_time);
164
165
166   pair = m->v4.message.hna.hna_net;
167
168   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
169     union olsr_ip_addr ip_addr;
170     if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) {
171       /* Only add HNA message if it contains data */
172       if (curr_size > OLSR_HNA_IPV4_HDRSIZE) {
173         OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
174         m->v4.seqno = htons(get_msg_seqno());
175         m->v4.olsr_msgsize = htons(curr_size);
176         net_outbuffer_push(ifp, msg_buffer, curr_size);
177         curr_size = OLSR_HNA_IPV4_HDRSIZE;
178         pair = m->v4.message.hna.hna_net;
179       }
180       net_output(ifp);
181       remainsize = net_outbuffer_bytes_left(ifp);
182       check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
183     }
184     OLSR_DEBUG(LOG_PACKET_CREATION, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
185     pair->addr = h->net.prefix.v4.s_addr;
186     olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
187     pair->netmask = ip_addr.v4.s_addr;
188     pair++;
189     curr_size += (2 * olsr_cnf->ipsize);
190   }
191   OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
192
193     m->v4.seqno = htons(get_msg_seqno());
194   m->v4.olsr_msgsize = htons(curr_size);
195
196   net_outbuffer_push(ifp, msg_buffer, curr_size);
197
198   return false;
199 }
200
201
202 /**
203  *IP version 6
204  *
205  *@param ifp the interface to send on
206  *@return nada
207  */
208 static bool
209 serialize_hna6(struct interface *ifp)
210 {
211   uint16_t remainsize, curr_size;
212   /* preserve existing data in output buffer */
213   union olsr_message *m;
214   struct hnapair6 *pair6;
215   union olsr_ip_addr tmp_netmask;
216   struct ip_prefix_entry *h;
217 #if !defined REMOVE_LOG_DEBUG
218   struct ipprefix_str prefixstr;
219 #endif
220
221   /* No hna nets */
222   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || list_is_empty(&olsr_cnf->hna_entries))
223     return false;
224
225
226   remainsize = net_outbuffer_bytes_left(ifp);
227
228   curr_size = OLSR_HNA_IPV6_HDRSIZE;
229
230   /* Send pending packet if not room in buffer */
231   if (curr_size > remainsize) {
232     net_output(ifp);
233     remainsize = net_outbuffer_bytes_left(ifp);
234   }
235   check_buffspace(curr_size, remainsize, "HNA");
236
237   m = (union olsr_message *)msg_buffer;
238
239   /* Fill header */
240   m->v6.originator = olsr_cnf->router_id.v6;
241   m->v6.hopcnt = 0;
242   m->v6.ttl = MAX_TTL;
243   m->v6.olsr_msgtype = HNA_MESSAGE;
244   m->v6.olsr_vtime = reltime_to_me(olsr_cnf->hna_params.validity_time);
245
246   pair6 = m->v6.message.hna.hna_net;
247
248
249   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h) {
250     if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) {
251       /* Only add HNA message if it contains data */
252       if (curr_size > OLSR_HNA_IPV6_HDRSIZE) {
253         OLSR_DEBUG(LOG_PACKET_CREATION, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
254         m->v6.seqno = htons(get_msg_seqno());
255         m->v6.olsr_msgsize = htons(curr_size);
256         net_outbuffer_push(ifp, msg_buffer, curr_size);
257         curr_size = OLSR_HNA_IPV6_HDRSIZE;
258         pair6 = m->v6.message.hna.hna_net;
259       }
260       net_output(ifp);
261       remainsize = net_outbuffer_bytes_left(ifp);
262       check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
263     }
264     OLSR_DEBUG(LOG_PACKET_CREATION, "\tNet: %s\n", olsr_ip_prefix_to_string(&prefixstr, &h->net));
265     pair6->addr = h->net.prefix.v6;
266     olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
267     pair6->netmask = tmp_netmask.v6;
268     pair6++;
269     curr_size += (2 * olsr_cnf->ipsize);
270   }
271   OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
272
273     m->v6.olsr_msgsize = htons(curr_size);
274   m->v6.seqno = htons(get_msg_seqno());
275
276   net_outbuffer_push(ifp, msg_buffer, curr_size);
277   return false;
278 }
279
280 /*
281  * Local Variables:
282  * c-basic-offset: 2
283  * indent-tabs-mode: nil
284  * End:
285  */