1 /*
2 * The olsr.org Optimized Link-State Routing daemon (olsrd)
3 *
4 * (c) by the OLSR project
5 *
6 * See our Git repository to find out who worked on this file
7 * and thus is a copyright holder on it.
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 * * Neither the name of olsr.org, olsrd nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 * Visit http://www.olsr.org for more information.
39 *
40 * If you find this software useful feel free to make a donation
41 * to the project. For more information see the website or contact
42 * the copyright holders.
43 *
44 */
45
46 /* -------------------------------------------------------------------------
47 * File : parse.c
48 * Description : functions to parse received zebra packets
49 * ------------------------------------------------------------------------- */
50
51 #include "defs.h"
52 #include "olsr.h"
53
54 #include "common.h"
55 #include "packet.h"
56 #include "client.h"
57 #include "parse.h"
58
59 static void free_zroute(struct zroute *);
60 static struct zroute *zparse_route(unsigned char *);
61
62 static void
free_zroute(struct zroute * r)63 free_zroute(struct zroute *r)
64 {
65
66 if(r->ifindex_num)
67 free(r->ifindex);
68 if(r->nexthop_num)
69 free(r->nexthop);
70
71 }
72
73 static struct zroute
zparse_route(unsigned char * opt)74 *zparse_route(unsigned char *opt)
75 {
76 struct zroute *r;
77 int c;
78 size_t size;
79 uint16_t length;
80 unsigned char *pnt;
81
82 memcpy(&length, opt, sizeof length);
83 length = ntohs (length);
84
85 r = olsr_malloc(sizeof *r, "QUAGGA: New zebra route");
86 pnt = &opt[3];
87 switch (zebra.version) {
88 case 0:
89 break;
90 case 1:
91 case 2:
92 pnt = &opt[6];
93 break;
94 default:
95 olsr_exit("QUAGGA: Unsupported zebra packet version", EXIT_FAILURE);
96 break;
97 }
98 r->type = *pnt++;
99 r->flags = *pnt++;
100 r->message = *pnt++;
101 r->prefixlen = *pnt++;
102 size = (r->prefixlen + 7) / 8;
103 memset(&r->prefix, 0, sizeof r->prefix);
104 if (olsr_cnf->ip_version == AF_INET)
105 memcpy(&r->prefix.v4.s_addr, pnt, size);
106 else
107 memcpy(r->prefix.v6.s6_addr, pnt, size);
108 pnt += size;
109
110 if (r->message & ZAPI_MESSAGE_NEXTHOP) {
111 r->nexthop_num = *pnt++;
112 r->nexthop = olsr_malloc((sizeof *r->nexthop) * r->nexthop_num, "QUAGGA: New zebra route nexthop");
113 for (c = 0; c < r->nexthop_num; c++) {
114 if (olsr_cnf->ip_version == AF_INET) {
115 memcpy(&r->nexthop[c].v4.s_addr, pnt, sizeof r->nexthop[c].v4.s_addr);
116 pnt += sizeof r->nexthop[c].v4.s_addr;
117 } else {
118 memcpy(r->nexthop[c].v6.s6_addr, pnt, sizeof r->nexthop[c].v6.s6_addr);
119 pnt += sizeof r->nexthop[c].v6.s6_addr;
120 }
121 }
122 }
123
124 if (r->message & ZAPI_MESSAGE_IFINDEX) {
125 r->ifindex_num = *pnt++;
126 r->ifindex = olsr_malloc(sizeof(uint32_t) * r->ifindex_num, "QUAGGA: New zebra route ifindex");
127 for (c = 0; c < r->ifindex_num; c++) {
128 memcpy(&r->ifindex[c], pnt, sizeof r->ifindex[c]);
129 r->ifindex[c] = ntohl (r->ifindex[c]);
130 pnt += sizeof r->ifindex[c];
131 }
132 }
133 switch (zebra.version) {
134 case 0:
135 case 1:
136 case 2:
137 break;
138 default:
139 olsr_exit("QUAGGA: Unsupported zebra packet version", EXIT_FAILURE);
140 break;
141 }
142
143 if (r->message & ZAPI_MESSAGE_DISTANCE) {
144 r->distance = *pnt++;
145 }
146
147 // Quagga v0.98.6 BUG workaround: metric is always sent by zebra
148 // even without ZAPI_MESSAGE_METRIC message.
149 if ((r->message & ZAPI_MESSAGE_METRIC) || !zebra.version) {
150 memcpy(&r->metric, pnt, sizeof r->metric);
151 r->metric = ntohl(r->metric);
152 pnt += sizeof r->metric;
153 }
154
155 if (pnt - opt != length) {
156 olsr_exit("QUAGGA: Length does not match", EXIT_FAILURE);
157 }
158
159 return r;
160 }
161
162 void
zparse(void * foo)163 zparse(void *foo __attribute__ ((unused)))
164 {
165 unsigned char *data, *f;
166 uint16_t command;
167 uint16_t length;
168 ssize_t len;
169 struct zroute *route;
170
171 if (!(zebra.status & STATUS_CONNECTED)) {
172 zclient_reconnect();
173 return;
174 }
175 data = zclient_read(&len);
176 if (data) {
177 f = data;
178 do {
179 length = ntohs(*((uint16_t *)(void *) f));
180 if (!length) { // something weird happened
181 olsr_exit("QUAGGA: Zero message length", EXIT_FAILURE);
182 }
183
184 /* Zebra Protocol Header
185 *
186 * Version 0: 2 bytes length, 1 byte command
187 *
188 * Version 1: 2 bytes length, 1 byte marker, 1 byte version, 2 bytes command
189 */
190 switch (zebra.version) {
191 case 0:
192 command = f[2];
193 break;
194
195 case 1:
196 case 2:
197 if ((f[2] != ZEBRA_HEADER_MARKER) || (f[3] != zebra.version)) {
198 olsr_exit("QUAGGA: Invalid zebra header received", EXIT_FAILURE);
199 }
200
201 command = ntohs(*((uint16_t *)(void *) &f[4]));
202 break;
203
204 default:
205 olsr_exit("QUAGGA: Unsupported zebra packet version", EXIT_FAILURE);
206 break;
207 }
208
209 if (olsr_cnf->ip_version == AF_INET) {
210 switch (command) {
211 case ZEBRA_IPV4_ROUTE_ADD:
212 route = zparse_route(f);
213 ip_prefix_list_add(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
214 free_zroute(route);
215 free(route);
216 break;
217
218 case ZEBRA_IPV4_ROUTE_DELETE:
219 route = zparse_route(f);
220 ip_prefix_list_remove(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
221 free_zroute(route);
222 free(route);
223 break;
224
225 default:
226 break;
227 }
228 } else {
229 switch (command) {
230 case ZEBRA_IPV6_ROUTE_ADD:
231 route = zparse_route(f);
232 ip_prefix_list_add(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
233 free_zroute(route);
234 free(route);
235 break;
236
237 case ZEBRA_IPV6_ROUTE_DELETE:
238 route = zparse_route(f);
239 ip_prefix_list_remove(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
240 free_zroute(route);
241 free(route);
242 break;
243
244 default:
245 break;
246 }
247 }
248
249 f += length;
250 }
251 while ((f - data) < len);
252
253 free(data);
254 }
255 }
256
257 /*
258 * Local Variables:
259 * c-basic-offset: 2
260 * indent-tabs-mode: nil
261 * End:
262 */
263