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