Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / isc-dhcp / common / raw.c
1 /* socket.c
2
3    BSD raw socket interface code... */
4
5 /* XXX
6
7    It's not clear how this should work, and that lack of clarity is
8    terribly detrimental to the NetBSD 1.1 kernel - it crashes and
9    burns.
10
11    Using raw sockets ought to be a big win over using BPF or something
12    like it, because you don't need to deal with the complexities of
13    the physical layer, but it appears not to be possible with existing
14    raw socket implementations.  This may be worth revisiting in the
15    future.  For now, this code can probably be considered a curiosity.
16    Sigh. */
17
18 /*
19  * Copyright (c) 1995-2002 Internet Software Consortium.
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  *
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. Neither the name of The Internet Software Consortium nor the names
32  *    of its contributors may be used to endorse or promote products derived
33  *    from this software without specific prior written permission.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
36  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
37  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
40  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  * This software has been written for the Internet Software Consortium
50  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
51  * To learn more about the Internet Software Consortium, see
52  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
53  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
54  * ``http://www.nominum.com''.
55  */
56
57 #ifndef lint
58 static char copyright[] =
59 "$Id: raw.c,v 1.17.2.1 2002/11/17 02:26:59 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium.  All rights reserved.\n";
60 #endif /* not lint */
61
62 #include "dhcpd.h"
63
64 #if defined (USE_RAW_SEND)
65 #include <sys/uio.h>
66
67 /* Generic interface registration routine... */
68 void if_register_send (info)
69         struct interface_info *info;
70 {
71         struct sockaddr_in name;
72         int sock;
73         struct socklist *tmp;
74         int flag;
75
76         /* Set up the address we're going to connect to. */
77         name.sin_family = AF_INET;
78         name.sin_port = local_port;
79         name.sin_addr.s_addr = htonl (INADDR_BROADCAST);
80         memset (name.sin_zero, 0, sizeof (name.sin_zero));
81
82         /* List addresses on which we're listening. */
83         if (!quiet_interface_discovery)
84                 log_info ("Sending on %s, port %d",
85                       piaddr (info -> address), htons (local_port));
86         if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
87                 log_fatal ("Can't create dhcp socket: %m");
88
89         /* Set the BROADCAST option so that we can broadcast DHCP responses. */
90         flag = 1;
91         if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
92                         &flag, sizeof flag) < 0)
93                 log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m");
94
95         /* Set the IP_HDRINCL flag so that we can supply our own IP
96            headers... */
97         if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &flag, sizeof flag) < 0)
98                 log_fatal ("Can't set IP_HDRINCL flag: %m");
99
100         info -> wfdesc = sock;
101         if (!quiet_interface_discovery)
102                 log_info ("Sending on   Raw/%s%s%s",
103                       info -> name,
104                       (info -> shared_network ? "/" : ""),
105                       (info -> shared_network ?
106                        info -> shared_network -> name : ""));
107 }
108
109 void if_deregister_send (info)
110         struct interface_info *info;
111 {
112         close (info -> wfdesc);
113         info -> wfdesc = -1;
114
115         if (!quiet_interface_discovery)
116                 log_info ("Disabling output on Raw/%s%s%s",
117                       info -> name,
118                       (info -> shared_network ? "/" : ""),
119                       (info -> shared_network ?
120                        info -> shared_network -> name : ""));
121 }
122
123 size_t send_packet (interface, packet, raw, len, from, to, hto)
124         struct interface_info *interface;
125         struct packet *packet;
126         struct dhcp_packet *raw;
127         size_t len;
128         struct in_addr from;
129         struct sockaddr_in *to;
130         struct hardware *hto;
131 {
132         unsigned char buf [256];
133         int bufp = 0;
134         struct iovec iov [2];
135         int result;
136
137         /* Assemble the headers... */
138         assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
139                                 to -> sin_addr.s_addr, to -> sin_port,
140                                 (unsigned char *)raw, len);
141
142         /* Fire it off */
143         iov [0].iov_base = (char *)buf;
144         iov [0].iov_len = bufp;
145         iov [1].iov_base = (char *)raw;
146         iov [1].iov_len = len;
147
148         result = writev(interface -> wfdesc, iov, 2);
149         if (result < 0)
150                 log_error ("send_packet: %m");
151         return result;
152 }
153 #endif /* USE_SOCKET_SEND */