More descriptive messages
[olsrd.git] / lib / quagga / src / parse.c
1 /*
2  * OLSRd Quagga plugin
3  *
4  * Copyright (C) 2006-2008 Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>
5  * Copyright (C) 2007-2010 Vasilis Tsiligiannis <acinonyxs@yahoo.gr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation or - at your option - under
10  * the terms of the GNU General Public Licence version 2 but can be
11  * linked to any BSD-Licenced Software with public available sourcecode
12  *
13  */
14
15 /* -------------------------------------------------------------------------
16  * File               : parse.c
17  * Description        : functions to parse received zebra packets
18  * ------------------------------------------------------------------------- */
19
20 #include "defs.h"
21 #include "olsr.h"
22
23 #include "common.h"
24 #include "packet.h"
25 #include "client.h"
26 #include "parse.h"
27
28 static void free_zroute(struct zroute *);
29 static struct zroute *zparse_route(unsigned char *);
30
31 static void
32 free_zroute(struct zroute *r)
33 {
34
35   if(r->ifindex_num)
36     free(r->ifindex);
37   if(r->nexthop_num)
38     free(r->nexthop);
39
40 }
41
42 static struct zroute
43 *zparse_route(unsigned char *opt)
44 {
45   struct zroute *r;
46   int c;
47   size_t size;
48   uint16_t length;
49   unsigned char *pnt;
50
51   memcpy(&length, opt, sizeof length);
52   length = ntohs (length);
53
54   r = olsr_malloc(sizeof *r, "QUAGGA: New zebra route");
55   pnt = (zebra.version ? &opt[6] : &opt[3]);
56   r->type = *pnt++;
57   r->flags = *pnt++;
58   r->message = *pnt++;
59   r->prefixlen = *pnt++;
60   size = (r->prefixlen + 7) / 8;
61   memset(&r->prefix, 0, sizeof r->prefix);
62   if (olsr_cnf->ip_version == AF_INET)
63     memcpy(&r->prefix.v4.s_addr, pnt, size);
64   else
65     memcpy(r->prefix.v6.s6_addr, pnt, size);
66   pnt += size;
67
68   switch (zebra.version) {
69     case 0:
70     case 1:
71       if (r->message & ZAPI_MESSAGE_NEXTHOP) {
72         r->nexthop_num = *pnt++;
73         r->nexthop = olsr_malloc((sizeof *r->nexthop) * r->nexthop_num, "QUAGGA: New zebra route nexthop");
74         for (c = 0; c < r->nexthop_num; c++) {
75           if (olsr_cnf->ip_version == AF_INET) {
76             memcpy(&r->nexthop[c].v4.s_addr, pnt, sizeof r->nexthop[c].v4.s_addr);
77             pnt += sizeof r->nexthop[c].v4.s_addr;
78           } else {
79             memcpy(r->nexthop[c].v6.s6_addr, pnt, sizeof r->nexthop[c].v6.s6_addr);
80             pnt += sizeof r->nexthop[c].v6.s6_addr;
81           }
82         }
83       }
84
85       if (r->message & ZAPI_MESSAGE_IFINDEX) {
86         r->ifindex_num = *pnt++;
87         r->ifindex = olsr_malloc(sizeof(uint32_t) * r->ifindex_num, "QUAGGA: New zebra route ifindex");
88         for (c = 0; c < r->ifindex_num; c++) {
89           memcpy(&r->ifindex[c], pnt, sizeof r->ifindex[c]);
90           r->ifindex[c] = ntohl (r->ifindex[c]);
91           pnt += sizeof r->ifindex[c];
92         }
93       }
94       break;
95     default:
96       OLSR_PRINTF(1, "(QUAGGA) Unsupported zebra packet version!\n");
97       break;
98   }
99
100   if (r->message & ZAPI_MESSAGE_DISTANCE) {
101     r->distance = *pnt++;
102   }
103
104 // Quagga v0.98.6 BUG workaround: metric is always sent by zebra
105 // even without ZAPI_MESSAGE_METRIC message.
106 //  if (r.message & ZAPI_MESSAGE_METRIC) {
107     memcpy(&r->metric, pnt, sizeof r->metric);
108     r->metric = ntohl(r->metric);
109     pnt += sizeof r->metric;
110 //  }
111
112   if (pnt - opt != length) {
113     olsr_exit("(QUAGGA) Length does not match!", EXIT_FAILURE);
114   }
115
116   return r;
117 }
118
119 void
120 zparse(void *foo __attribute__ ((unused)))
121 {
122   unsigned char *data, *f;
123   uint16_t command;
124   uint16_t length;
125   ssize_t len;
126   struct zroute *route;
127
128   if (!(zebra.status & STATUS_CONNECTED)) {
129     zclient_reconnect();
130     return;
131   }
132   data = zclient_read(&len);
133   if (data) {
134     f = data;
135     do {
136       memcpy(&length, f, sizeof length);
137       length = ntohs (length);
138       if (!length) // something weired happened
139         olsr_exit("(QUAGGA) Zero message length!", EXIT_FAILURE);
140       if (zebra.version) {
141         if ((f[2] != ZEBRA_HEADER_MARKER) || (f[3] != zebra.version))
142           olsr_exit("(QUAGGA) Invalid zebra header received!", EXIT_FAILURE);
143         memcpy(&command, &f[4], sizeof command);
144         command = ntohs (command);
145       } else
146           command = f[2];
147       if (olsr_cnf->ip_version == AF_INET) {
148         switch (command) {
149           case ZEBRA_IPV4_ROUTE_ADD:
150             route = zparse_route(f);
151             ip_prefix_list_add(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
152             free_zroute(route);
153             free(route);
154             break;
155           case ZEBRA_IPV4_ROUTE_DELETE:
156             route = zparse_route(f);
157             ip_prefix_list_remove(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
158             free_zroute(route);
159             free(route);
160             break;
161           default:
162             break;
163         }
164       } else {
165         switch (command) {
166           case ZEBRA_IPV6_ROUTE_ADD:
167             route = zparse_route(f);
168             ip_prefix_list_add(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
169             free_zroute(route);
170             free(route);
171             break;
172           case ZEBRA_IPV6_ROUTE_DELETE:
173             route = zparse_route(f);
174             ip_prefix_list_remove(&olsr_cnf->hna_entries, &route->prefix, route->prefixlen);
175             free_zroute(route);
176             free(route);
177             break;
178           default:
179             break;
180         }
181       }
182
183       f += length;
184     }
185     while ((f - data) < len);
186     free(data);
187   }
188
189 }
190
191 /*
192  * Local Variables:
193  * c-basic-offset: 2
194  * indent-tabs-mode: nil
195  * End:
196  */