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