File: | src/usr.sbin/dvmrpd/report.c |
Warning: | line 252, column 14 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: report.c,v 1.11 2015/12/07 18:59:31 mmcc Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org> | |||
5 | * | |||
6 | * Permission to use, copy, modify, and distribute this software for any | |||
7 | * purpose with or without fee is hereby granted, provided that the above | |||
8 | * copyright notice and this permission notice appear in all copies. | |||
9 | * | |||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
17 | */ | |||
18 | ||||
19 | #include <sys/types.h> | |||
20 | #include <sys/socket.h> | |||
21 | #include <netinet/in.h> | |||
22 | #include <netinet/ip.h> | |||
23 | #include <arpa/inet.h> | |||
24 | ||||
25 | #include <stdlib.h> | |||
26 | #include <string.h> | |||
27 | ||||
28 | #include "igmp.h" | |||
29 | #include "dvmrpd.h" | |||
30 | #include "dvmrp.h" | |||
31 | #include "dvmrpe.h" | |||
32 | #include "log.h" | |||
33 | ||||
34 | extern struct dvmrpd_conf *deconf; | |||
35 | ||||
36 | void rr_list_remove(struct route_report *); | |||
37 | ||||
38 | /* DVMRP report packet handling */ | |||
39 | int | |||
40 | send_report(struct iface *iface, struct in_addr addr, void *data, int len) | |||
41 | { | |||
42 | struct sockaddr_in dst; | |||
43 | struct ibuf *buf; | |||
44 | struct dvmrp_hdr *dvmrp_hdr; | |||
45 | int ret = 0; | |||
46 | ||||
47 | log_debug("send_report: interface %s addr %s", | |||
48 | iface->name, inet_ntoa(addr)); | |||
49 | ||||
50 | if (iface->passive) | |||
51 | return (0); | |||
52 | ||||
53 | if ((buf = ibuf_open(iface->mtu - sizeof(struct ip))) == NULL((void *)0)) | |||
54 | fatal("send_report"); | |||
55 | ||||
56 | /* DVMRP header */ | |||
57 | if (gen_dvmrp_hdr(buf, iface, DVMRP_CODE_REPORT0x02)) | |||
58 | goto fail; | |||
59 | ||||
60 | ibuf_add(buf, data, len); | |||
61 | ||||
62 | dst.sin_family = AF_INET2; | |||
63 | dst.sin_len = sizeof(struct sockaddr_in); | |||
64 | dst.sin_addr.s_addr = addr.s_addr; | |||
65 | ||||
66 | /* update chksum */ | |||
67 | dvmrp_hdr = ibuf_seek(buf, 0, sizeof(*dvmrp_hdr)); | |||
68 | dvmrp_hdr->chksum = in_cksum(buf->buf, buf->wpos); | |||
69 | ||||
70 | ret = send_packet(iface, buf->buf, buf->wpos, &dst); | |||
71 | ibuf_free(buf); | |||
72 | return (ret); | |||
73 | fail: | |||
74 | log_warn("send_report"); | |||
75 | ibuf_free(buf); | |||
76 | return (-1); | |||
77 | } | |||
78 | ||||
79 | void | |||
80 | recv_report(struct nbr *nbr, char *buf, u_int16_t len) | |||
81 | { | |||
82 | struct route_report rr; | |||
83 | u_int32_t netid, netmask; | |||
84 | u_int8_t metric, netid_len, prefixlen; | |||
85 | ||||
86 | log_debug("recv_report: neighbor ID %s", inet_ntoa(nbr->id)); | |||
87 | ||||
88 | if ((nbr->state != NBR_STA_2_WAY0x04) && (!nbr->compat)) { | |||
89 | log_warnx("recv_report: neighbor %s not in state %s", | |||
90 | inet_ntoa(nbr->id), "2-WAY"); | |||
91 | return; | |||
92 | } | |||
93 | ||||
94 | /* parse route report */ | |||
95 | do { | |||
96 | /* | |||
97 | * get netmask | |||
98 | * | |||
99 | * The netmask in a DVMRP report is only represented by 3 bytes, | |||
100 | * to cope with that we read 4 bytes and shift 8 bits. | |||
101 | * The most significant part of the mask is always 255. | |||
102 | */ | |||
103 | ||||
104 | /* read four bytes */ | |||
105 | memcpy(&netmask, buf, sizeof(netmask)); | |||
106 | /* ditch one byte, since we only need three */ | |||
107 | netmask = ntohl(netmask)(__uint32_t)(__builtin_constant_p(netmask) ? (__uint32_t)(((__uint32_t )(netmask) & 0xff) << 24 | ((__uint32_t)(netmask) & 0xff00) << 8 | ((__uint32_t)(netmask) & 0xff0000) >> 8 | ((__uint32_t)(netmask) & 0xff000000) >> 24) : __swap32md (netmask)) >> 8; | |||
108 | netmask = htonl(netmask)(__uint32_t)(__builtin_constant_p(netmask) ? (__uint32_t)(((__uint32_t )(netmask) & 0xff) << 24 | ((__uint32_t)(netmask) & 0xff00) << 8 | ((__uint32_t)(netmask) & 0xff0000) >> 8 | ((__uint32_t)(netmask) & 0xff000000) >> 24) : __swap32md (netmask)); | |||
109 | ||||
110 | /* set the highest byte to 255 */ | |||
111 | netmask |= htonl(0xff000000)(__uint32_t)(__builtin_constant_p(0xff000000) ? (__uint32_t)( ((__uint32_t)(0xff000000) & 0xff) << 24 | ((__uint32_t )(0xff000000) & 0xff00) << 8 | ((__uint32_t)(0xff000000 ) & 0xff0000) >> 8 | ((__uint32_t)(0xff000000) & 0xff000000) >> 24) : __swap32md(0xff000000)); | |||
112 | buf += 3; | |||
113 | len -= 3; | |||
114 | ||||
115 | prefixlen = mask2prefixlen(netmask); | |||
116 | netid_len = PREFIX_SIZE(prefixlen)(((prefixlen) + 7) / 8); | |||
117 | ||||
118 | do { | |||
119 | /* | |||
120 | * get netid | |||
121 | * | |||
122 | * The length of the netid is depending on the above | |||
123 | * netmask. | |||
124 | * Read 4 bytes and use the netmask from above to | |||
125 | * determine the netid. | |||
126 | */ | |||
127 | memcpy(&netid, buf, sizeof(netid)); | |||
128 | netid &= netmask; | |||
129 | ||||
130 | buf += netid_len; | |||
131 | len -= netid_len; | |||
132 | ||||
133 | /* get metric */ | |||
134 | memcpy(&metric, buf, sizeof(metric)); | |||
135 | buf += sizeof(metric); | |||
136 | len -= sizeof(metric); | |||
137 | ||||
138 | rr.net.s_addr = netid; | |||
139 | rr.mask.s_addr = netmask; | |||
140 | rr.nexthop = nbr->id; | |||
141 | rr.metric = (metric & METRIC_MASK~0x80); | |||
142 | ||||
143 | /* ifindex */ | |||
144 | rr.ifindex = nbr->iface->ifindex; | |||
145 | ||||
146 | /* send route report to RDE */ | |||
147 | dvmrpe_imsg_compose_rde(IMSG_ROUTE_REPORT, nbr->peerid, | |||
148 | 0, &rr, sizeof(rr)); | |||
149 | ||||
150 | } while (!(metric & LAST_MASK0x80) && (len > 0)); | |||
151 | } while (len > 0); | |||
152 | ||||
153 | return; | |||
154 | } | |||
155 | ||||
156 | /* timers */ | |||
157 | void | |||
158 | report_timer(int fd, short event, void *arg) | |||
159 | { | |||
160 | struct timeval tv; | |||
161 | ||||
162 | /* request full route report */ | |||
163 | dvmrpe_imsg_compose_rde(IMSG_FULL_ROUTE_REPORT, 0, 0, NULL((void *)0), 0); | |||
164 | ||||
165 | /* restart report timer */ | |||
166 | timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0; | |||
167 | tv.tv_sec = ROUTE_REPORT_INTERVAL60; | |||
168 | evtimer_add(&deconf->report_timer, &tv)event_add(&deconf->report_timer, &tv); | |||
169 | } | |||
170 | ||||
171 | int | |||
172 | start_report_timer(void) | |||
173 | { | |||
174 | struct timeval tv; | |||
175 | ||||
176 | timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0; | |||
177 | tv.tv_sec = MIN_FLASH_UPDATE_INTERVAL5; /* XXX safe?? */ | |||
178 | return (evtimer_add(&deconf->report_timer, &tv)event_add(&deconf->report_timer, &tv)); | |||
179 | } | |||
180 | ||||
181 | int | |||
182 | stop_report_timer(void) | |||
183 | { | |||
184 | return (evtimer_del(&deconf->report_timer)event_del(&deconf->report_timer)); | |||
185 | } | |||
186 | ||||
187 | /* route report list */ | |||
188 | void | |||
189 | rr_list_add(struct rr_head *rr_list, struct route_report *rr) | |||
190 | { | |||
191 | struct rr_entry *le; | |||
192 | ||||
193 | if (rr == NULL((void *)0)) | |||
194 | fatalx("rr_list_add: no route report"); | |||
195 | ||||
196 | if ((le = calloc(1, sizeof(*le))) == NULL((void *)0)) | |||
197 | fatal("rr_list_add"); | |||
198 | ||||
199 | TAILQ_INSERT_TAIL(rr_list, le, entry)do { (le)->entry.tqe_next = ((void *)0); (le)->entry.tqe_prev = (rr_list)->tqh_last; *(rr_list)->tqh_last = (le); (rr_list )->tqh_last = &(le)->entry.tqe_next; } while (0); | |||
200 | le->re = rr; | |||
201 | rr->refcount++; | |||
202 | } | |||
203 | ||||
204 | void | |||
205 | rr_list_remove(struct route_report *rr) | |||
206 | { | |||
207 | if (--rr->refcount == 0) | |||
208 | free(rr); | |||
209 | } | |||
210 | ||||
211 | void | |||
212 | rr_list_clr(struct rr_head *rr_list) | |||
213 | { | |||
214 | struct rr_entry *le; | |||
215 | ||||
216 | while ((le = TAILQ_FIRST(rr_list)((rr_list)->tqh_first)) != NULL((void *)0)) { | |||
217 | TAILQ_REMOVE(rr_list, le, entry)do { if (((le)->entry.tqe_next) != ((void *)0)) (le)->entry .tqe_next->entry.tqe_prev = (le)->entry.tqe_prev; else ( rr_list)->tqh_last = (le)->entry.tqe_prev; *(le)->entry .tqe_prev = (le)->entry.tqe_next; ; ; } while (0); | |||
218 | rr_list_remove(le->re); | |||
219 | free(le); | |||
220 | } | |||
221 | } | |||
222 | ||||
223 | void | |||
224 | rr_list_send(struct rr_head *rr_list, struct iface *xiface, struct nbr *nbr) | |||
225 | { | |||
226 | struct rr_entry *le, *le2; | |||
227 | struct ibuf *buf; | |||
228 | struct iface *iface; | |||
229 | struct in_addr addr; | |||
230 | u_int32_t netid, netmask; | |||
231 | u_int8_t metric, netid_len, prefixlen; | |||
232 | ||||
233 | /* set destination */ | |||
234 | if (xiface == NULL((void *)0)) { | |||
| ||||
235 | /* directly to a nbr */ | |||
236 | iface = nbr->iface; | |||
237 | addr = nbr->addr; | |||
238 | } else { | |||
239 | /* multicast on interface */ | |||
240 | iface = xiface; | |||
241 | inet_aton(AllDVMRPRouters"224.0.0.4", &addr); | |||
242 | } | |||
243 | ||||
244 | while (!TAILQ_EMPTY(rr_list)(((rr_list)->tqh_first) == ((void *)0))) { | |||
245 | if ((buf = ibuf_open(iface->mtu - sizeof(struct ip))) == NULL((void *)0)) | |||
246 | fatal("rr_list_send"); | |||
247 | ||||
248 | prefixlen = 0; | |||
249 | while (((le = TAILQ_FIRST(rr_list)((rr_list)->tqh_first)) != NULL((void *)0)) && | |||
250 | (buf->wpos < 1000)) { | |||
251 | /* netmask */ | |||
252 | netmask = le->re->mask.s_addr; | |||
| ||||
253 | if (prefixlen != mask2prefixlen(netmask)) { | |||
254 | prefixlen = mask2prefixlen(netmask); | |||
255 | netmask = ntohl(netmask)(__uint32_t)(__builtin_constant_p(netmask) ? (__uint32_t)(((__uint32_t )(netmask) & 0xff) << 24 | ((__uint32_t)(netmask) & 0xff00) << 8 | ((__uint32_t)(netmask) & 0xff0000) >> 8 | ((__uint32_t)(netmask) & 0xff000000) >> 24) : __swap32md (netmask)) << 8; | |||
256 | netmask = htonl(netmask)(__uint32_t)(__builtin_constant_p(netmask) ? (__uint32_t)(((__uint32_t )(netmask) & 0xff) << 24 | ((__uint32_t)(netmask) & 0xff00) << 8 | ((__uint32_t)(netmask) & 0xff0000) >> 8 | ((__uint32_t)(netmask) & 0xff000000) >> 24) : __swap32md (netmask)); | |||
257 | ibuf_add(buf, &netmask, 3); | |||
258 | } | |||
259 | netid_len = PREFIX_SIZE(prefixlen)(((prefixlen) + 7) / 8); | |||
260 | ||||
261 | /* netid */ | |||
262 | netid = le->re->net.s_addr; | |||
263 | ibuf_add(buf, &netid, netid_len); | |||
264 | ||||
265 | /* metric */ | |||
266 | if (iface->ifindex == le->re->ifindex) | |||
267 | /* poison reverse */ | |||
268 | metric = le->re->metric + INFINITY_METRIC31; | |||
269 | else | |||
270 | metric = le->re->metric; | |||
271 | ||||
272 | /* | |||
273 | * determine if we need to flag last entry with current | |||
274 | * netmask. | |||
275 | */ | |||
276 | le2 = TAILQ_NEXT(le, entry)((le)->entry.tqe_next); | |||
277 | if (le2 != NULL((void *)0)) { | |||
278 | if (mask2prefixlen(le2->re->mask.s_addr) != | |||
279 | prefixlen) | |||
280 | metric = metric | LAST_MASK0x80; | |||
281 | } else { | |||
282 | metric = metric | LAST_MASK0x80; | |||
283 | } | |||
284 | ||||
285 | ibuf_add(buf, &metric, sizeof(metric)); | |||
286 | ||||
287 | TAILQ_REMOVE(rr_list, le, entry)do { if (((le)->entry.tqe_next) != ((void *)0)) (le)->entry .tqe_next->entry.tqe_prev = (le)->entry.tqe_prev; else ( rr_list)->tqh_last = (le)->entry.tqe_prev; *(le)->entry .tqe_prev = (le)->entry.tqe_next; ; ; } while (0); | |||
288 | rr_list_remove(le->re); | |||
289 | free(le); | |||
290 | } | |||
291 | send_report(iface, addr, buf->buf, buf->wpos); | |||
292 | ibuf_free(buf); | |||
293 | } | |||
294 | } |