common/raw.c

Go to the documentation of this file.
00001 /* raw.c
00002 
00003    BSD raw socket interface code... */
00004 
00005 /* XXX
00006 
00007    It's not clear how this should work, and that lack of clarity is
00008    terribly detrimental to the NetBSD 1.1 kernel - it crashes and
00009    burns.
00010 
00011    Using raw sockets ought to be a big win over using BPF or something
00012    like it, because you don't need to deal with the complexities of
00013    the physical layer, but it appears not to be possible with existing
00014    raw socket implementations.  This may be worth revisiting in the
00015    future.  For now, this code can probably be considered a curiosity.
00016    Sigh. */
00017 
00018 /*
00019  * Copyright (c) 2004,2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC")
00020  * Copyright (c) 1995-2003 by Internet Software Consortium
00021  *
00022  * Permission to use, copy, modify, and distribute this software for any
00023  * purpose with or without fee is hereby granted, provided that the above
00024  * copyright notice and this permission notice appear in all copies.
00025  *
00026  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00027  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00028  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00029  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00030  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00031  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00032  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00033  *
00034  *   Internet Systems Consortium, Inc.
00035  *   950 Charter Street
00036  *   Redwood City, CA 94063
00037  *   <info@isc.org>
00038  *   https://www.isc.org/
00039  *
00040  */
00041 
00042 #include "dhcpd.h"
00043 
00044 #if defined (USE_RAW_SEND)
00045 #include <sys/uio.h>
00046 
00047 /* Generic interface registration routine... */
00048 void if_register_send (info)
00049         struct interface_info *info;
00050 {
00051         struct sockaddr_in name;
00052         int sock;
00053         struct socklist *tmp;
00054         int flag;
00055 
00056         /* Set up the address we're going to connect to. */
00057         name.sin_family = AF_INET;
00058         name.sin_port = local_port;
00059         name.sin_addr.s_addr = htonl (INADDR_BROADCAST);
00060         memset (name.sin_zero, 0, sizeof (name.sin_zero));
00061 
00062         /* List addresses on which we're listening. */
00063         if (!quiet_interface_discovery)
00064                 log_info ("Sending on %s, port %d",
00065                       piaddr (info -> address), htons (local_port));
00066         if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
00067                 log_fatal ("Can't create dhcp socket: %m");
00068 
00069         /* Set the BROADCAST option so that we can broadcast DHCP responses. */
00070         flag = 1;
00071         if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
00072                         &flag, sizeof flag) < 0)
00073                 log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m");
00074 
00075         /* Set the IP_HDRINCL flag so that we can supply our own IP
00076            headers... */
00077         if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &flag, sizeof flag) < 0)
00078                 log_fatal ("Can't set IP_HDRINCL flag: %m");
00079 
00080         info -> wfdesc = sock;
00081         if (!quiet_interface_discovery)
00082                 log_info ("Sending on   Raw/%s%s%s",
00083                       info -> name,
00084                       (info -> shared_network ? "/" : ""),
00085                       (info -> shared_network ?
00086                        info -> shared_network -> name : ""));
00087 }
00088 
00089 void if_deregister_send (info)
00090         struct interface_info *info;
00091 {
00092         close (info -> wfdesc);
00093         info -> wfdesc = -1;
00094 
00095         if (!quiet_interface_discovery)
00096                 log_info ("Disabling output on Raw/%s%s%s",
00097                       info -> name,
00098                       (info -> shared_network ? "/" : ""),
00099                       (info -> shared_network ?
00100                        info -> shared_network -> name : ""));
00101 }
00102 
00103 size_t send_packet (interface, packet, raw, len, from, to, hto)
00104         struct interface_info *interface;
00105         struct packet *packet;
00106         struct dhcp_packet *raw;
00107         size_t len;
00108         struct in_addr from;
00109         struct sockaddr_in *to;
00110         struct hardware *hto;
00111 {
00112         unsigned char buf [256];
00113         int bufp = 0;
00114         struct iovec iov [2];
00115         int result;
00116 
00117         /* Assemble the headers... */
00118         assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
00119                                 to -> sin_addr.s_addr, to -> sin_port,
00120                                 (unsigned char *)raw, len);
00121 
00122         /* Fire it off */
00123         iov [0].iov_base = (char *)buf;
00124         iov [0].iov_len = bufp;
00125         iov [1].iov_base = (char *)raw;
00126         iov [1].iov_len = len;
00127 
00128         result = writev(interface -> wfdesc, iov, 2);
00129         if (result < 0)
00130                 log_error ("send_packet: %m");
00131         return result;
00132 }
00133 #endif /* USE_SOCKET_SEND */

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1