From decf33c222ad6578e176a31df5de8d9a88ebb2cd Mon Sep 17 00:00:00 2001 From: Ted Lemon Date: Thu, 11 Apr 1996 06:44:12 +0000 Subject: [PATCH] Initial interface discovery and input dispatch routines --- common/dispatch.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++ dispatch.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 348 insertions(+) create mode 100644 common/dispatch.c create mode 100644 dispatch.c diff --git a/common/dispatch.c b/common/dispatch.c new file mode 100644 index 00000000..b237cb10 --- /dev/null +++ b/common/dispatch.c @@ -0,0 +1,174 @@ +/* socket.c + + BSD socket interface code... */ + +/* + * Copyright (c) 1995, 1996 The Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie + * Enterprises. To learn more about the Internet Software Consortium, + * see ``http://www.vix.com/isc''. To learn more about Vixie + * Enterprises, see ``http://www.vix.com''. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" +#include + +struct interface_info *interfaces; + +/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces. + For each interface that's of type INET and not the loopback interface, + register that interface with the network I/O software, figure out what + subnet it's on, and add it to the list of interfaces. */ + +void get_interface_list () +{ + struct interface_info *tmp; + static char buf [8192]; + struct ifconf ic; + int i; + int sock; + int ifcount = 0; + int ifix = 0; + + /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */ + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + error ("Can't create addrlist socket"); + + /* Get the interface configuration information... */ + ic.ifc_len = sizeof buf; + ic.ifc_ifcu.ifcu_buf = (caddr_t)buf; + i = ioctl(sock, SIOCGIFCONF, &ic); + close (sock); + if (i < 0) + error ("ioctl: SIOCGIFCONF: %m"); + + /* Cycle through the list of interfaces looking for IP addresses. + Go through twice; once to count the number if addresses, and a + second time to copy them into an array of addresses. */ + for (i = 0; i < ic.ifc_len;) { + struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i); +#ifdef HAVE_SIN_LEN + i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len; +#else + i += sizeof *ifp; +#endif + if (ifp -> ifr_addr.sa_family == AF_INET) { + struct sockaddr_in *foo = + (struct sockaddr_in *)(&ifp -> ifr_addr); + /* We don't want the loopback interface. */ + if (foo -> sin_addr.s_addr == INADDR_LOOPBACK) + continue; + tmp = ((struct interface_info *) + dmalloc (sizeof *tmp, "get_interface_list")); + if (!tmp) + error ("Insufficient memory to " + "record interface"); + memset (tmp, 0, sizeof *tmp); + tmp -> address.len = 4; + memcpy (tmp -> address.iabuf, &foo -> sin_addr.s_addr); + tmp -> local_subnet = find_subnet (tmp -> address); + if_register_send (tmp, ifp); + if_register_receive (tmp, ifp); + } + } +} + +/* Wait for packets to come in using select(). When one does, call + receive_packet to receive the packet and possibly strip hardware + addressing information from it, and then call do_packet to try to + do something with it. */ + +void dispatch () +{ + struct sockaddr_in from; + struct hardware_addr hfrom; + struct iaddr ifrom; + fd_set r, w, x; + struct interface_info *l; + int max = 0; + int count; + int result; + static unsigned char packbuf [4095]; /* Packet input buffer. + Must be as large as largest + possible MTU. */ + + FD_ZERO (&r); + FD_ZERO (&w); + FD_ZERO (&x); + + do { + /* Set up the read mask. */ + for (l = sockets; l; l = l -> next) { + FD_SET (l -> sock, &r); + FD_SET (l -> sock, &x); + if (l -> sock > max) + max = l -> sock; + } + + /* Wait for a packet or a timeout... XXX */ + count = select (max + 1, &r, &w, &x, (struct timeval *)0); + + /* Get the current time... */ + GET_TIME (&cur_time); + + /* Not likely to be transitory... */ + if (count < 0) + error ("select: %m"); + + for (l = interfaces; l; l = l -> next) { + if (!FD_ISSET (l -> rfdesc, &r)) + continue; + if ((result = + receive_packet (l, packbuf, sizeof packbuf, + &from, &hfrom)) < 0) { + warn ("receive_packet failed on %s: %m", + inet_ntoa (l -> addr.sin_addr)); + continue; + } + note ("request from %s, port %d", + inet_ntoa (from.sin_addr), + htons (from.sin_port)); + ifrom.len = 4; + memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); + + do_packet (l, packbuf, result, + from.sin_port, ifrom, hfrom); + } + } while (1); +} + diff --git a/dispatch.c b/dispatch.c new file mode 100644 index 00000000..b237cb10 --- /dev/null +++ b/dispatch.c @@ -0,0 +1,174 @@ +/* socket.c + + BSD socket interface code... */ + +/* + * Copyright (c) 1995, 1996 The Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie + * Enterprises. To learn more about the Internet Software Consortium, + * see ``http://www.vix.com/isc''. To learn more about Vixie + * Enterprises, see ``http://www.vix.com''. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" +#include + +struct interface_info *interfaces; + +/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces. + For each interface that's of type INET and not the loopback interface, + register that interface with the network I/O software, figure out what + subnet it's on, and add it to the list of interfaces. */ + +void get_interface_list () +{ + struct interface_info *tmp; + static char buf [8192]; + struct ifconf ic; + int i; + int sock; + int ifcount = 0; + int ifix = 0; + + /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */ + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + error ("Can't create addrlist socket"); + + /* Get the interface configuration information... */ + ic.ifc_len = sizeof buf; + ic.ifc_ifcu.ifcu_buf = (caddr_t)buf; + i = ioctl(sock, SIOCGIFCONF, &ic); + close (sock); + if (i < 0) + error ("ioctl: SIOCGIFCONF: %m"); + + /* Cycle through the list of interfaces looking for IP addresses. + Go through twice; once to count the number if addresses, and a + second time to copy them into an array of addresses. */ + for (i = 0; i < ic.ifc_len;) { + struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i); +#ifdef HAVE_SIN_LEN + i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len; +#else + i += sizeof *ifp; +#endif + if (ifp -> ifr_addr.sa_family == AF_INET) { + struct sockaddr_in *foo = + (struct sockaddr_in *)(&ifp -> ifr_addr); + /* We don't want the loopback interface. */ + if (foo -> sin_addr.s_addr == INADDR_LOOPBACK) + continue; + tmp = ((struct interface_info *) + dmalloc (sizeof *tmp, "get_interface_list")); + if (!tmp) + error ("Insufficient memory to " + "record interface"); + memset (tmp, 0, sizeof *tmp); + tmp -> address.len = 4; + memcpy (tmp -> address.iabuf, &foo -> sin_addr.s_addr); + tmp -> local_subnet = find_subnet (tmp -> address); + if_register_send (tmp, ifp); + if_register_receive (tmp, ifp); + } + } +} + +/* Wait for packets to come in using select(). When one does, call + receive_packet to receive the packet and possibly strip hardware + addressing information from it, and then call do_packet to try to + do something with it. */ + +void dispatch () +{ + struct sockaddr_in from; + struct hardware_addr hfrom; + struct iaddr ifrom; + fd_set r, w, x; + struct interface_info *l; + int max = 0; + int count; + int result; + static unsigned char packbuf [4095]; /* Packet input buffer. + Must be as large as largest + possible MTU. */ + + FD_ZERO (&r); + FD_ZERO (&w); + FD_ZERO (&x); + + do { + /* Set up the read mask. */ + for (l = sockets; l; l = l -> next) { + FD_SET (l -> sock, &r); + FD_SET (l -> sock, &x); + if (l -> sock > max) + max = l -> sock; + } + + /* Wait for a packet or a timeout... XXX */ + count = select (max + 1, &r, &w, &x, (struct timeval *)0); + + /* Get the current time... */ + GET_TIME (&cur_time); + + /* Not likely to be transitory... */ + if (count < 0) + error ("select: %m"); + + for (l = interfaces; l; l = l -> next) { + if (!FD_ISSET (l -> rfdesc, &r)) + continue; + if ((result = + receive_packet (l, packbuf, sizeof packbuf, + &from, &hfrom)) < 0) { + warn ("receive_packet failed on %s: %m", + inet_ntoa (l -> addr.sin_addr)); + continue; + } + note ("request from %s, port %d", + inet_ntoa (from.sin_addr), + htons (from.sin_port)); + ifrom.len = 4; + memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); + + do_packet (l, packbuf, result, + from.sin_port, ifrom, hfrom); + } + } while (1); +} +