xref: /netbsd-src/external/mpl/dhcp/dist/common/raw.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
1 /*	$NetBSD: raw.c,v 1.4 2022/04/03 01:10:58 christos Exp $	*/
2 
3 /* raw.c
4 
5    BSD raw socket interface code... */
6 
7 /* XXX
8 
9    It's not clear how this should work, and that lack of clarity is
10    terribly detrimental to the NetBSD 1.1 kernel - it crashes and
11    burns.
12 
13    Using raw sockets ought to be a big win over using BPF or something
14    like it, because you don't need to deal with the complexities of
15    the physical layer, but it appears not to be possible with existing
16    raw socket implementations.  This may be worth revisiting in the
17    future.  For now, this code can probably be considered a curiosity.
18    Sigh. */
19 
20 /*
21  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
22  * Copyright (c) 1995-2003 by Internet Software Consortium
23  *
24  * This Source Code Form is subject to the terms of the Mozilla Public
25  * License, v. 2.0. If a copy of the MPL was not distributed with this
26  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
29  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
30  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
31  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
32  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
33  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
34  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35  *
36  *   Internet Systems Consortium, Inc.
37  *   PO Box 360
38  *   Newmarket, NH 03857 USA
39  *   <info@isc.org>
40  *   https://www.isc.org/
41  *
42  */
43 
44 #include <sys/cdefs.h>
45 __RCSID("$NetBSD: raw.c,v 1.4 2022/04/03 01:10:58 christos Exp $");
46 
47 #include "dhcpd.h"
48 
49 #if defined (USE_RAW_SEND)
50 #include <sys/uio.h>
51 
52 /* Generic interface registration routine... */
if_register_send(info)53 void if_register_send (info)
54 	struct interface_info *info;
55 {
56 	struct sockaddr_in name;
57 	int sock;
58 	struct socklist *tmp;
59 	int flag;
60 
61 	/* Set up the address we're going to connect to. */
62 	name.sin_family = AF_INET;
63 	name.sin_port = relay_port ? relay_port : *libdhcp_callbacks.local_port;
64 	name.sin_addr.s_addr = htonl (INADDR_BROADCAST);
65 	memset (name.sin_zero, 0, sizeof (name.sin_zero));
66 
67 	/* List addresses on which we're listening. */
68         if (!quiet_interface_discovery)
69 		log_info ("Sending on %s, port %d",
70 		      piaddr (info -> address), htons (name.sin_port));
71 	if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
72 		log_fatal ("Can't create dhcp socket: %m");
73 
74 	/* Set the BROADCAST option so that we can broadcast DHCP responses. */
75 	flag = 1;
76 	if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
77 			&flag, sizeof flag) < 0)
78 		log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m");
79 
80 	/* Set the IP_HDRINCL flag so that we can supply our own IP
81 	   headers... */
82 	if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &flag, sizeof flag) < 0)
83 		log_fatal ("Can't set IP_HDRINCL flag: %m");
84 
85 	info -> wfdesc = sock;
86         if (!quiet_interface_discovery)
87 		log_info ("Sending on   Raw/%s%s%s",
88 		      info -> name,
89 		      (info -> shared_network ? "/" : ""),
90 		      (info -> shared_network ?
91 		       info -> shared_network -> name : ""));
92 }
93 
if_deregister_send(info)94 void if_deregister_send (info)
95 	struct interface_info *info;
96 {
97 	close (info -> wfdesc);
98 	info -> wfdesc = -1;
99 
100         if (!quiet_interface_discovery)
101 		log_info ("Disabling output on Raw/%s%s%s",
102 		      info -> name,
103 		      (info -> shared_network ? "/" : ""),
104 		      (info -> shared_network ?
105 		       info -> shared_network -> name : ""));
106 }
107 
send_packet(interface,packet,raw,len,from,to,hto)108 size_t send_packet (interface, packet, raw, len, from, to, hto)
109 	struct interface_info *interface;
110 	struct packet *packet;
111 	struct dhcp_packet *raw;
112 	size_t len;
113 	struct in_addr from;
114 	struct sockaddr_in *to;
115 	struct hardware *hto;
116 {
117 	unsigned char buf [256];
118 	int bufp = 0;
119 	struct iovec iov [2];
120 	int result;
121 
122 	/* Assemble the headers... */
123 	assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
124 				to -> sin_addr.s_addr, to -> sin_port,
125 				(unsigned char *)raw, len);
126 
127 	/* Fire it off */
128 	iov [0].iov_base = (char *)buf;
129 	iov [0].iov_len = bufp;
130 	iov [1].iov_base = (char *)raw;
131 	iov [1].iov_len = len;
132 
133 	result = writev(interface -> wfdesc, iov, 2);
134 	if (result < 0)
135 		log_error ("send_packet: %m");
136 	return result;
137 }
138 #endif /* USE_SOCKET_SEND */
139