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