GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ripd/message.c Lines: 0 203 0.0 %
Date: 2017-11-07 Branches: 0 88 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: message.c,v 1.12 2014/10/25 03:23:49 lteo Exp $ */
2
3
/*
4
 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
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
#include <netinet/udp.h>
25
26
#include <stdlib.h>
27
#include <string.h>
28
29
#include "ripd.h"
30
#include "rip.h"
31
#include "ripe.h"
32
#include "log.h"
33
34
extern struct ripd_conf	*oeconf;
35
36
void	 delete_entry(struct rip_route *);
37
38
/* timers */
39
/* ARGSUSED */
40
void
41
report_timer(int fd, short event, void *arg)
42
{
43
	struct timeval	 tv;
44
45
	ripe_imsg_compose_rde(IMSG_FULL_RESPONSE, 0, 0, NULL, 0);
46
47
	/* restart report timer */
48
	timerclear(&tv);
49
	tv.tv_sec = KEEPALIVE + arc4random_uniform(OFFSET);
50
	evtimer_add(&oeconf->report_timer, &tv);
51
}
52
53
int
54
start_report_timer(void)
55
{
56
	struct timeval	 tv;
57
58
	timerclear(&tv);
59
	tv.tv_sec = KEEPALIVE + arc4random_uniform(OFFSET);
60
	return (evtimer_add(&oeconf->report_timer, &tv));
61
}
62
63
/* list handlers */
64
void
65
add_entry(struct packet_head *r_list, struct rip_route *rr)
66
{
67
	struct packet_entry	*re;
68
69
	if (rr == NULL)
70
		fatalx("add_entry: no route report");
71
72
	if ((re = calloc(1, sizeof(*re))) == NULL)
73
		fatal("add_response");
74
75
	TAILQ_INSERT_TAIL(r_list, re, entry);
76
	re->rr = rr;
77
	rr->refcount++;
78
}
79
80
void
81
delete_entry(struct rip_route *rr)
82
{
83
	if (--rr->refcount == 0)
84
		free(rr);
85
}
86
87
void
88
clear_list(struct packet_head *r_list)
89
{
90
	struct packet_entry	*re;
91
92
	while ((re = TAILQ_FIRST(r_list)) != NULL) {
93
		TAILQ_REMOVE(r_list, re, entry);
94
		delete_entry(re->rr);
95
		free(re);
96
	}
97
}
98
99
/* communications */
100
int
101
send_triggered_update(struct iface *iface, struct rip_route *rr)
102
{
103
	struct sockaddr_in	 dst;
104
	struct ibuf		*buf;
105
	u_int16_t		 afi, route_tag;
106
	u_int32_t		 address, netmask, nexthop, metric;
107
108
	inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr);
109
110
	dst.sin_port = htons(RIP_PORT);
111
	dst.sin_family = AF_INET;
112
	dst.sin_len = sizeof(struct sockaddr_in);
113
114
	if (iface->passive)
115
		return (0);
116
117
	if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) -
118
	    sizeof(struct udphdr))) == NULL)
119
		fatal("send_triggered_update");
120
121
	gen_rip_hdr(buf, COMMAND_RESPONSE);
122
123
	afi = htons(AF_INET);
124
	route_tag = 0;
125
126
	address = rr->address.s_addr;
127
	netmask = rr->mask.s_addr;
128
	nexthop = rr->nexthop.s_addr;
129
	metric = htonl(rr->metric);
130
131
	ibuf_add(buf, &afi, sizeof(afi));
132
	ibuf_add(buf, &route_tag, sizeof(route_tag));
133
	ibuf_add(buf, &address, sizeof(address));
134
	ibuf_add(buf, &netmask, sizeof(netmask));
135
	ibuf_add(buf, &nexthop, sizeof(nexthop));
136
	ibuf_add(buf, &metric, sizeof(metric));
137
138
	send_packet(iface, buf->buf, buf->wpos, &dst);
139
	ibuf_free(buf);
140
141
	return (0);
142
}
143
144
int
145
send_request(struct packet_head *r_list, struct iface *i, struct nbr *nbr)
146
{
147
	struct ibuf		*buf;
148
	struct iface		*iface;
149
	struct packet_entry	*entry;
150
	struct sockaddr_in	 dst;
151
	u_int8_t		 nentries;
152
	u_int8_t		 single_entry = 0;
153
	u_int32_t		 address, netmask, nexthop;
154
	u_int16_t		 port, afi, route_tag;
155
	u_int32_t		 metric;
156
157
	if (i == NULL) {
158
		/* directly to a nbr */
159
		iface = nbr->iface;
160
		dst.sin_addr = nbr->addr;
161
		port = htons(nbr->port);
162
	} else {
163
		/* multicast on interface */
164
		iface = i;
165
		inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr);
166
		port = htons(RIP_PORT);
167
	}
168
169
	dst.sin_port = port;
170
	dst.sin_family = AF_INET;
171
	dst.sin_len = sizeof(struct sockaddr_in);
172
173
	if (iface->passive)
174
		return (0);
175
176
	while (!TAILQ_EMPTY(r_list)) {
177
		if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) -
178
		    sizeof(struct udphdr))) == NULL)
179
			fatal("send_request");
180
181
		gen_rip_hdr(buf, COMMAND_REQUEST);
182
183
		route_tag = 0;
184
		nentries = 0;
185
186
		if (TAILQ_FIRST(r_list) == TAILQ_LAST(r_list, packet_head))
187
			single_entry = 1;
188
		while (((entry = TAILQ_FIRST(r_list)) != NULL) &&
189
		    nentries < MAX_RIP_ENTRIES) {
190
			afi = htons(AF_INET);
191
192
			address = entry->rr->address.s_addr;
193
			netmask = entry->rr->mask.s_addr;
194
			nexthop = entry->rr->nexthop.s_addr;
195
			metric = htonl(entry->rr->metric);
196
197
			if (metric == htonl(INFINITY) && single_entry)
198
				afi = AF_UNSPEC;
199
200
			ibuf_add(buf, &afi, sizeof(afi));
201
			ibuf_add(buf, &route_tag, sizeof(route_tag));
202
			ibuf_add(buf, &address, sizeof(address));
203
			ibuf_add(buf, &netmask, sizeof(netmask));
204
			ibuf_add(buf, &nexthop, sizeof(nexthop));
205
			ibuf_add(buf, &metric, sizeof(metric));
206
207
			TAILQ_REMOVE(r_list, entry, entry);
208
			delete_entry(entry->rr);
209
			free(entry);
210
			nentries++;
211
		}
212
		send_packet(iface, buf->buf, buf->wpos, &dst);
213
		ibuf_free(buf);
214
	}
215
216
	return (0);
217
}
218
219
int
220
send_response(struct packet_head *r_list, struct iface *i, struct nbr *nbr)
221
{
222
	struct ibuf		*buf;
223
	struct iface		*iface;
224
	struct packet_entry	*entry;
225
	struct sockaddr_in	 dst;
226
	u_int8_t		 nentries;
227
	u_int16_t		 port, afi, route_tag;
228
	u_int32_t		 address, netmask, nexthop;
229
	u_int32_t		 metric;
230
231
	if (i == NULL) {
232
		/* directly to a nbr */
233
		iface = nbr->iface;
234
		dst.sin_addr = nbr->addr;
235
		port = htons(nbr->port);
236
	} else {
237
		/* multicast on interface */
238
		iface = i;
239
		inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr);
240
		port = htons(RIP_PORT);
241
	}
242
243
	dst.sin_port = port;
244
	dst.sin_family = AF_INET;
245
	dst.sin_len = sizeof(struct sockaddr_in);
246
247
	if (iface->passive)
248
		return (0);
249
250
	while (!TAILQ_EMPTY(r_list)) {
251
		if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) -
252
		    sizeof(struct udphdr))) == NULL)
253
			fatal("send_response");
254
255
		gen_rip_hdr(buf, COMMAND_RESPONSE);
256
257
		afi = htons(AF_INET);
258
		route_tag = 0;
259
		nentries = 0;
260
261
		if (iface->auth_type != AUTH_NONE) {
262
			if (auth_gen(buf, iface) == -1) {
263
				ibuf_free(buf);
264
				return (-1);
265
			}
266
			nentries++;
267
		}
268
269
		while ((entry = TAILQ_FIRST(r_list)) != NULL &&
270
		    nentries < MAX_RIP_ENTRIES) {
271
			address = entry->rr->address.s_addr;
272
			netmask = entry->rr->mask.s_addr;
273
			nexthop = entry->rr->nexthop.s_addr;
274
			metric = htonl(entry->rr->metric);
275
276
			if (entry->rr->ifindex == iface->ifindex) {
277
				if (oeconf->options & OPT_SPLIT_HORIZON)
278
					goto free;
279
				else if (oeconf->options & OPT_SPLIT_POISONED)
280
					metric = htonl(INFINITY);
281
			}
282
283
			/* If the nexthop is not reachable through the
284
			 * outgoing interface set it to INADDR_ANY */
285
			if ((nexthop & iface->mask.s_addr) !=
286
			    (iface->addr.s_addr & iface->mask.s_addr))
287
				nexthop = INADDR_ANY;
288
289
			ibuf_add(buf, &afi, sizeof(afi));
290
			ibuf_add(buf, &route_tag, sizeof(route_tag));
291
			ibuf_add(buf, &address, sizeof(address));
292
			ibuf_add(buf, &netmask, sizeof(netmask));
293
			ibuf_add(buf, &nexthop, sizeof(nexthop));
294
			ibuf_add(buf, &metric, sizeof(metric));
295
free:
296
			TAILQ_REMOVE(r_list, entry, entry);
297
			delete_entry(entry->rr);
298
			free(entry);
299
			nentries++;
300
		}
301
302
		if (iface->auth_type == AUTH_CRYPT)
303
			auth_add_trailer(buf, iface);
304
305
		send_packet(iface, buf->buf, buf->wpos, &dst);
306
		ibuf_free(buf);
307
	}
308
309
	return (0);
310
}
311
312
void
313
recv_request(struct iface *i, struct nbr *nbr, u_int8_t *buf, u_int16_t len)
314
{
315
	struct rip_entry	*e;
316
	struct rip_route	 rr;
317
	int			 l = len;
318
319
	bzero(&rr, sizeof(rr));
320
321
	if (len < RIP_ENTRY_LEN) {
322
		log_debug("recv_request: bad packet size, interface %s",
323
		    i->name);
324
		return;
325
	}
326
327
	/*
328
	 * XXX is it guaranteed that bus is properly aligned.
329
	 * If not this will bomb on strict alignment archs.
330
	 * */
331
	e = (struct rip_entry *)buf;
332
333
	if (len > RIP_ENTRY_LEN * MAX_RIP_ENTRIES) {
334
		log_debug("recv_request: packet too long\n");
335
		return;
336
	}
337
338
	l -= RIP_ENTRY_LEN;
339
340
	/*
341
	 * If there is exactly one entry in the request, and it has
342
	 * an address family identifier of zero and a metric of
343
	 * infinity (i.e., 16), then this is a request to send the
344
	 * entire routing table.
345
	 */
346
	if (e->AFI == 0 && e->metric == ntohl(INFINITY) && l == 0) {
347
		ripe_imsg_compose_rde(IMSG_FULL_RESPONSE, nbr->peerid,
348
		    0, NULL, 0);
349
		return;
350
	}
351
352
	for ( ; l >= 0; l -= RIP_ENTRY_LEN) {
353
		if (e->AFI != AF_INET) {
354
			log_debug("recv_request: AFI %d not supported\n",
355
			    e->AFI);
356
			return;
357
		}
358
		rr.address.s_addr = e->address;
359
		rr.mask.s_addr = e->mask;
360
		rr.nexthop.s_addr = e->nexthop;
361
		rr.metric = e->metric;
362
		rr.ifindex = i->ifindex;
363
364
		ripe_imsg_compose_rde(IMSG_ROUTE_REQUEST, nbr->peerid,
365
		    0, &rr, sizeof(rr));
366
367
		e++;
368
	}
369
370
	ripe_imsg_compose_rde(IMSG_ROUTE_REQUEST_END, nbr->peerid,
371
	    0, NULL, 0);
372
}
373
374
void
375
recv_response(struct iface *i, struct nbr *nbr, u_int8_t *buf, u_int16_t len)
376
{
377
	struct rip_route	 r;
378
	struct rip_entry	*e;
379
	int			 l;
380
381
	if (len < RIP_ENTRY_LEN) {
382
		log_debug("recv_response: bad packet size, interface %s",
383
		    i->name);
384
		return;
385
	}
386
387
	/* We must double check the length, because the only entry
388
	 * can be stripped off by authentication code
389
	 */
390
	if (len < RIP_ENTRY_LEN) {
391
		/* If there are no entries, our work is finished here */
392
		return;
393
	}
394
395
	/* XXX again */
396
	e = (struct rip_entry *)buf;
397
398
	if (len > RIP_ENTRY_LEN * MAX_RIP_ENTRIES) {
399
		log_debug("recv_response: packet too long\n");
400
		return;
401
	}
402
403
	l = len - sizeof(*e);
404
405
	for ( ; l >= 0; l -= RIP_ENTRY_LEN) {
406
		if (ntohs(e->AFI) != AF_INET) {
407
			log_debug("recv_response: AFI %d not supported\n",
408
			    e->AFI);
409
			return;
410
		}
411
412
		r.address.s_addr = e->address;
413
		r.mask.s_addr = e->mask;
414
415
		if (e->nexthop == INADDR_ANY ||
416
		    ((i->addr.s_addr & i->mask.s_addr) !=
417
		    (e->nexthop & i->mask.s_addr)))
418
			r.nexthop.s_addr = nbr->addr.s_addr;
419
		else
420
			r.nexthop.s_addr = e->nexthop;
421
422
		r.metric = ntohl(e->metric);
423
		r.ifindex = i->ifindex;
424
425
		ripe_imsg_compose_rde(IMSG_ROUTE_FEED, 0, 0, &r, sizeof(r));
426
427
		e++;
428
	}
429
}