From: Ted Lemon Date: Sat, 17 Oct 1998 13:35:24 +0000 (+0000) Subject: Move discover_interfaces and relate goop to discover.c X-Git-Tag: carrel-2~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7d77172d26458cf02878c3d5bbe13d7141c2412a;p=thirdparty%2Fdhcp.git Move discover_interfaces and relate goop to discover.c --- diff --git a/common/dispatch.c b/common/dispatch.c index cea517ee8..ee1f170f2 100644 --- a/common/dispatch.c +++ b/common/dispatch.c @@ -3,7 +3,7 @@ Network input dispatcher... */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,368 +42,16 @@ #ifndef lint static char copyright[] = -"$Id: dispatch.c,v 1.50 1998/06/25 02:55:16 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dispatch.c,v 1.51 1998/10/17 13:35:24 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" -#include -struct interface_info *interfaces, *dummy_interfaces; struct protocol *protocols; struct timeout *timeouts; static struct timeout *free_timeouts; -static int interfaces_invalidated; -void (*bootp_packet_handler) PROTO ((struct interface_info *, - struct dhcp_packet *, int, unsigned int, - struct iaddr, struct hardware *)); -static void got_one PROTO ((struct protocol *)); -int quiet_interface_discovery; - -/* 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 discover_interfaces (state) - int state; -{ - struct interface_info *tmp; - struct interface_info *last, *next; - char buf [8192]; - struct ifconf ic; - struct ifreq ifr; - int i; - int sock; - int address_count = 0; - struct subnet *subnet; - struct shared_network *share; - struct sockaddr_in foo; - int ir; -#ifdef ALIAS_NAMES_PERMUTED - char *s; -#endif -#ifdef USE_FALLBACK - static struct shared_network fallback_network; -#endif - - /* 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); - - if (i < 0) - error ("ioctl: SIOCGIFCONF: %m"); - - /* If we already have a list of interfaces, and we're running as - a DHCP server, the interfaces were requested. */ - if (interfaces && (state == DISCOVER_SERVER || - state == DISCOVER_RELAY || - state == DISCOVER_REQUESTED)) - ir = 0; - else if (state == DISCOVER_UNCONFIGURED) - ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC; - else - ir = INTERFACE_REQUESTED; - - /* Cycle through the list of interfaces looking for IP addresses. - Go through twice; once to count the number of 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_SA_LEN - if (ifp -> ifr_addr.sa_len) - i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len; - else -#endif - i += sizeof *ifp; - -#ifdef ALIAS_NAMES_PERMUTED - if ((s = strrchr (ifp -> ifr_name, ':'))) { - *s = 0; - } -#endif - -#ifdef SKIP_DUMMY_INTERFACES - if (!strncmp (ifp -> ifr_name, "dummy", 5)) - continue; -#endif - - - /* See if this is the sort of interface we want to - deal with. */ - strcpy (ifr.ifr_name, ifp -> ifr_name); - if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) - error ("Can't get interface flags for %s: %m", - ifr.ifr_name); - - /* Skip loopback, point-to-point and down interfaces, - except don't skip down interfaces if we're trying to - get a list of configurable interfaces. */ - if ((ifr.ifr_flags & IFF_LOOPBACK) || -#ifdef IFF_POINTOPOINT - (ifr.ifr_flags & IFF_POINTOPOINT) || -#endif - (!(ifr.ifr_flags & IFF_UP) && - state != DISCOVER_UNCONFIGURED)) - continue; - - /* See if we've seen an interface that matches this one. */ - for (tmp = interfaces; tmp; tmp = tmp -> next) - if (!strcmp (tmp -> name, ifp -> ifr_name)) - break; - - /* If there isn't already an interface by this name, - allocate one. */ - if (!tmp) { - tmp = ((struct interface_info *) - dmalloc (sizeof *tmp, "discover_interfaces")); - if (!tmp) - error ("Insufficient memory to %s %s", - "record interface", ifp -> ifr_name); - strcpy (tmp -> name, ifp -> ifr_name); - tmp -> next = interfaces; - tmp -> flags = ir; - interfaces = tmp; - } - - /* If we have the capability, extract link information - and record it in a linked list. */ -#ifdef AF_LINK - if (ifp -> ifr_addr.sa_family == AF_LINK) { - struct sockaddr_dl *foo = ((struct sockaddr_dl *) - (&ifp -> ifr_addr)); -#if defined (HAVE_SIN_LEN) - tmp -> hw_address.hlen = foo -> sdl_alen; -#else - tmp -> hw_address.hlen = 6; /* XXX!!! */ -#endif - tmp -> hw_address.htype = HTYPE_ETHER; /* XXX */ - memcpy (tmp -> hw_address.haddr, - LLADDR (foo), tmp -> hw_address.hlen); - } else -#endif /* AF_LINK */ - - if (ifp -> ifr_addr.sa_family == AF_INET) { - struct iaddr addr; - -#if defined (SIOCGIFHWADDR) && !defined (AF_LINK) - struct ifreq ifr; - struct sockaddr sa; - int b, sk; - - /* Read the hardware address from this interface. */ - ifr = *ifp; - if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0) - error ("Can't get hardware address for %s: %m", - ifr.ifr_name); - - sa = *(struct sockaddr *)&ifr.ifr_hwaddr; - - switch (sa.sa_family) { -#ifdef ARPHRD_LOOPBACK - case ARPHRD_LOOPBACK: - /* ignore loopback interface */ - break; -#endif - - case ARPHRD_ETHER: - tmp -> hw_address.hlen = 6; - tmp -> hw_address.htype = ARPHRD_ETHER; - memcpy (tmp -> hw_address.haddr, - sa.sa_data, 6); - break; - -#ifndef ARPHRD_IEEE802 -# define ARPHRD_IEEE802 HTYPE_IEEE802 -#endif - case ARPHRD_IEEE802: - tmp -> hw_address.hlen = 6; - tmp -> hw_address.htype = ARPHRD_IEEE802; - memcpy (tmp -> hw_address.haddr, - sa.sa_data, 6); - break; - -#ifdef ARPHRD_METRICOM - case ARPHRD_METRICOM: - tmp -> hw_address.hlen = 6; - tmp -> hw_address.htype = ARPHRD_METRICOM; - memcpy (tmp -> hw_address.haddr, - sa.sa_data, 6); - - break; -#endif - - default: - error ("%s: unknown hardware address type %d", - ifr.ifr_name, sa.sa_family); - } -#endif /* defined (SIOCGIFHWADDR) && !defined (AF_LINK) */ - - /* Get a pointer to the address... */ - memcpy (&foo, &ifp -> ifr_addr, - sizeof ifp -> ifr_addr); - - /* We don't want the loopback interface. */ - if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK)) - continue; - - - /* If this is the first real IP address we've - found, keep a pointer to ifreq structure in - which we found it. */ - if (!tmp -> ifp) { - struct ifreq *tif; -#ifdef HAVE_SA_LEN - int len = ((sizeof ifp -> ifr_name) + - ifp -> ifr_addr.sa_len); -#else - int len = sizeof *ifp; -#endif - tif = (struct ifreq *)malloc (len); - if (!tif) - error ("no space to remember ifp."); - memcpy (tif, ifp, len); - tmp -> ifp = tif; - tmp -> primary_address = foo.sin_addr; - } - - /* Grab the address... */ - addr.len = 4; - memcpy (addr.iabuf, &foo.sin_addr.s_addr, - addr.len); - - /* If there's a registered subnet for this address, - connect it together... */ - if ((subnet = find_subnet (addr))) { - /* If this interface has multiple aliases - on the same subnet, ignore all but the - first we encounter. */ - if (!subnet -> interface) { - subnet -> interface = tmp; - subnet -> interface_address = addr; - } else if (subnet -> interface != tmp) { - warn ("Multiple %s %s: %s %s", - "interfaces match the", - "same subnet", - subnet -> interface -> name, - tmp -> name); - } - share = subnet -> shared_network; - if (tmp -> shared_network && - tmp -> shared_network != share) { - warn ("Interface %s matches %s", - tmp -> name, - "multiple shared networks"); - } else { - tmp -> shared_network = share; - } - - if (!share -> interface) { - share -> interface = tmp; - } else if (share -> interface != tmp) { - warn ("Multiple %s %s: %s %s", - "interfaces match the", - "same shared network", - share -> interface -> name, - tmp -> name); - } - } - } - } - - /* If we're just trying to get a list of interfaces that we might - be able to configure, we can quit now. */ - if (state == DISCOVER_UNCONFIGURED) - return; - - /* Weed out the interfaces that did not have IP addresses. */ - last = (struct interface_info *)0; - for (tmp = interfaces; tmp; tmp = next) { - next = tmp -> next; - if ((tmp -> flags & INTERFACE_AUTOMATIC) && - state == DISCOVER_REQUESTED) - tmp -> flags &= ~(INTERFACE_AUTOMATIC | - INTERFACE_REQUESTED); - if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) { - if ((tmp -> flags & INTERFACE_REQUESTED) != ir) - error ("%s: not found", tmp -> name); - if (!last) - interfaces = interfaces -> next; - else - last -> next = tmp -> next; - - /* Remember the interface in case we need to know - about it later. */ - tmp -> next = dummy_interfaces; - dummy_interfaces = tmp; - continue; - } - last = tmp; - - memcpy (&foo, &tmp -> ifp -> ifr_addr, - sizeof tmp -> ifp -> ifr_addr); - - /* We must have a subnet declaration for each interface. */ - if (!tmp -> shared_network && (state == DISCOVER_SERVER)) - error ("No subnet declaration for %s (%s).", - tmp -> name, inet_ntoa (foo.sin_addr)); - - /* Find subnets that don't have valid interface - addresses... */ - for (subnet = (tmp -> shared_network - ? tmp -> shared_network -> subnets - : (struct subnet *)0); - subnet; subnet = subnet -> next_sibling) { - if (!subnet -> interface_address.len) { - /* Set the interface address for this subnet - to the first address we found. */ - subnet -> interface_address.len = 4; - memcpy (subnet -> interface_address.iabuf, - &foo.sin_addr.s_addr, 4); - } - } - - /* Register the interface... */ - if_register_receive (tmp); - if_register_send (tmp); - } - - /* Now register all the remaining interfaces as protocols. */ - for (tmp = interfaces; tmp; tmp = tmp -> next) - add_protocol (tmp -> name, tmp -> rfdesc, got_one, tmp); - - close (sock); - -#ifdef USE_FALLBACK - strcpy (fallback_interface.name, "fallback"); - fallback_interface.shared_network = &fallback_network; - fallback_network.name = "fallback-net"; - if_register_fallback (&fallback_interface); - add_protocol ("fallback", fallback_interface.wfdesc, - fallback_discard, &fallback_interface); -#endif -} - -void reinitialize_interfaces () -{ - struct interface_info *ip; - - for (ip = interfaces; ip; ip = ip -> next) { - if_reinitialize_receive (ip); - if_reinitialize_send (ip); - } - -#ifdef USE_FALLBACK - if_reinitialize_fallback (&fallback_interface); -#endif - - interfaces_invalidated = 1; -} +int interfaces_invalidated; #ifdef USE_POLL /* Wait for packets to come in using poll(). Anyway, when a packet @@ -570,38 +218,6 @@ void dispatch () } #endif /* USE_POLL */ -static void got_one (l) - struct protocol *l; -{ - struct sockaddr_in from; - struct hardware hfrom; - struct iaddr ifrom; - int result; - union { - unsigned char packbuf [4095]; /* Packet input buffer. - Must be as large as largest - possible MTU. */ - struct dhcp_packet packet; - } u; - struct interface_info *ip = l -> local; - - if ((result = - receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) { - warn ("receive_packet failed on %s: %m", ip -> name); - return; - } - if (result == 0) - return; - - if (bootp_packet_handler) { - ifrom.len = 4; - memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); - - (*bootp_packet_handler) (ip, &u.packet, result, - from.sin_port, ifrom, &hfrom); - } -} - int locate_network (packet) struct packet *packet; {