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