GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/dhcpd/icmp.c Lines: 0 56 0.0 %
Date: 2017-11-07 Branches: 0 22 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: icmp.c,v 1.18 2017/02/13 23:04:05 krw Exp $ */
2
3
/*
4
 * Copyright (c) 1997, 1998 The Internet Software Consortium.
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
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of The Internet Software Consortium nor the names
17
 *    of its contributors may be used to endorse or promote products derived
18
 *    from this software without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
21
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
 * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
25
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 *
34
 * This software has been written for the Internet Software Consortium
35
 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
36
 * Enterprises.  To learn more about the Internet Software Consortium,
37
 * see ``http://www.vix.com/isc''.  To learn more about Vixie
38
 * Enterprises, see ``http://www.vix.com''.
39
 */
40
41
#include <sys/types.h>
42
#include <sys/socket.h>
43
44
#include <arpa/inet.h>
45
46
#include <net/if.h>
47
48
#include <netinet/ip.h>
49
#include <netinet/ip_icmp.h>
50
51
#include <netdb.h>
52
#include <stdio.h>
53
#include <string.h>
54
#include <unistd.h>
55
56
#include "dhcp.h"
57
#include "tree.h"
58
#include "dhcpd.h"
59
#include "log.h"
60
61
static int icmp_protocol_initialized;
62
static int icmp_protocol_fd;
63
64
/* Initialize the ICMP protocol. */
65
66
void
67
icmp_startup(int routep, void (*handler)(struct iaddr, u_int8_t *, int))
68
{
69
	struct protoent *proto;
70
	int protocol = 1, state;
71
72
	/* Only initialize icmp once. */
73
	if (icmp_protocol_initialized)
74
		fatalx("attempted to reinitialize icmp protocol");
75
	icmp_protocol_initialized = 1;
76
77
	/* Get the protocol number (should be 1). */
78
	if ((proto = getprotobyname("icmp")) != NULL)
79
		protocol = proto->p_proto;
80
81
	/* Get a raw socket for the ICMP protocol. */
82
	if ((icmp_protocol_fd = socket(AF_INET, SOCK_RAW, protocol)) == -1)
83
		fatal("unable to create icmp socket");
84
85
	/* Make sure it does routing... */
86
	state = 0;
87
	if (setsockopt(icmp_protocol_fd, SOL_SOCKET, SO_DONTROUTE,
88
	    &state, sizeof(state)) == -1)
89
		fatal("Unable to disable SO_DONTROUTE on ICMP socket");
90
91
	add_protocol("icmp", icmp_protocol_fd, icmp_echoreply,
92
	    (void *)handler);
93
}
94
95
int
96
icmp_echorequest(struct iaddr *addr)
97
{
98
	struct sockaddr_in to;
99
	struct icmp icmp;
100
	int status;
101
102
	if (!icmp_protocol_initialized)
103
		fatalx("attempt to use ICMP protocol before initialization.");
104
105
	memset(&to, 0, sizeof(to));
106
	to.sin_len = sizeof to;
107
	to.sin_family = AF_INET;
108
	memcpy(&to.sin_addr, addr->iabuf, sizeof to.sin_addr);	/* XXX */
109
110
	icmp.icmp_type = ICMP_ECHO;
111
	icmp.icmp_code = 0;
112
	icmp.icmp_cksum = 0;
113
	icmp.icmp_seq = 0;
114
	icmp.icmp_id = getpid() & 0xffff;
115
116
	icmp.icmp_cksum = wrapsum(checksum((unsigned char *)&icmp,
117
	    sizeof(icmp), 0));
118
119
	/* Send the ICMP packet... */
120
	status = sendto(icmp_protocol_fd, &icmp, sizeof(icmp), 0,
121
	    (struct sockaddr *)&to, sizeof(to));
122
	if (status == -1)
123
		log_warn("icmp_echorequest %s", inet_ntoa(to.sin_addr));
124
125
	if (status != sizeof icmp)
126
		return 0;
127
	return 1;
128
}
129
130
void
131
icmp_echoreply(struct protocol *protocol)
132
{
133
	void (*handler)(struct iaddr, u_int8_t *, int);
134
	struct sockaddr_in from;
135
	u_int8_t icbuf[1500];
136
	struct icmp *icfrom;
137
	int status, len;
138
	socklen_t salen;
139
	struct iaddr ia;
140
141
	salen = sizeof from;
142
	status = recvfrom(protocol->fd, icbuf, sizeof(icbuf), 0,
143
	    (struct sockaddr *)&from, &salen);
144
	if (status == -1) {
145
		log_warn("icmp_echoreply");
146
		return;
147
	}
148
149
	/* Probably not for us. */
150
	if (status < (sizeof(struct ip)) + (sizeof *icfrom))
151
		return;
152
153
	len = status - sizeof(struct ip);
154
	icfrom = (struct icmp *)(icbuf + sizeof(struct ip));
155
156
	/* Silently discard ICMP packets that aren't echoreplies. */
157
	if (icfrom->icmp_type != ICMP_ECHOREPLY)
158
		return;
159
160
	/* If we were given a second-stage handler, call it. */
161
	if (protocol->local) {
162
		handler = ((void (*)(struct iaddr, u_int8_t *, int))
163
		    protocol->local);
164
		memcpy(ia.iabuf, &from.sin_addr, sizeof from.sin_addr);
165
		ia.len = sizeof from.sin_addr;
166
		(*handler)(ia, icbuf, len);
167
	}
168
}