static int choose_mirror(void) { char *list; char *countryarchive; int i; debconf_get(debconf, DEBCONF_BASE "country"); #ifndef WITH_FTP_MANUAL manual_entry = ! strcmp(debconf->value, MANUAL_ENTRY) || ! strcmp(debconf->value, MANUAL_ENTRY_OLD); #else if (! strcasecmp(protocol,"ftp") == 0) manual_entry = ! strcmp(debconf->value, MANUAL_ENTRY) || ! strcmp(debconf->value, MANUAL_ENTRY_OLD); else manual_entry = 1; #endif if (! manual_entry) { char *mir = add_protocol("mirror"); countryarchive=malloc(strlen(country) + strlen(".archive.ubuntu.com") + 1); for (i = 0; country[i]; ++i) countryarchive[i] = tolower((unsigned char) country[i]); strcpy(countryarchive + i, ".archive.ubuntu.com"); /* Prompt for mirror in selected country. */ list=debconf_list(mirrors_in(country)); debconf_subst(debconf, mir, "mirrors", list); if (debconf_fget(debconf, mir, "seen") != 0 || strcmp(debconf->value, "true") != 0) if (mirror_root(countryarchive)) debconf_set(debconf, mir, countryarchive); free(list); free(countryarchive); debconf_input(debconf, base_on_cd ? "medium" : "high", mir); free(mir); } else { char *host = add_protocol("hostname"); char *dir = add_protocol("directory"); /* Manual entry. */ debconf_input(debconf, "critical", host); debconf_input(debconf, "critical", dir); free(host); free(dir); } return 0; }
/* * Unset most relevant seen flags to allow to correct preseeded values * when mirror is bad. */ void unset_seen_flags(void) { char *hostname, *directory; hostname = add_protocol("hostname"); debconf_fset(debconf, hostname, "seen", "false"); free(hostname); directory = add_protocol("directory"); debconf_fset(debconf, directory, "seen", "false"); free(directory); debconf_fset(debconf, DEBCONF_BASE "country", "seen", "false"); debconf_fset(debconf, DEBCONF_BASE "suite", "seen", "false"); }
/* Check if the mirror carries the architecture that's being installed. */ int check_arch (void) { char *command; FILE *f = NULL; char *hostname, *directory, *suite = NULL; int valid = 0; hostname = add_protocol("hostname"); debconf_get(debconf, hostname); free(hostname); hostname = strdup(debconf->value); directory = add_protocol("directory"); debconf_get(debconf, directory); free(directory); directory = strdup(debconf->value); /* As suite has been determined previously, this should not fail */ debconf_get(debconf, DEBCONF_BASE "suite"); if (strlen(debconf->value) > 0) { suite = strdup(debconf->value); asprintf(&command, "wget -q %s://%s%s/dists/%s/main/binary-%s/Release -O - | grep Architecture", protocol, hostname, directory, suite, ARCH_TEXT); di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command); f = popen(command, "r"); free(command); if (f != NULL) { char buf[SUITE_LENGTH]; if (fgets(buf, SUITE_LENGTH - 1, f)) if (strlen(buf) > 1) valid = 1; } pclose(f); } free(hostname); free(directory); if (suite) free(suite); if (valid) { return 0; } else { di_log(DI_LOG_LEVEL_DEBUG, "Architecture not supported by selected mirror"); debconf_input(debconf, "critical", DEBCONF_BASE "noarch"); if (debconf_go(debconf) == 30) exit(10); /* back up to menu */ else return 1; /* back to beginning of questions */ } }
void L3Socket::add_ip_addr(unsigned char* ip_str,unsigned char* netmask){ BOOST_LOG_TRIVIAL(debug) << ifname <<" Start Working ARP"; ARPProtocolHandler* arp_hdl = ARPProtocolHandler::getInstance(); add_protocol(arp_hdl); in_addr ip; inet_aton((const char* )ip_str,&ip); IPProtocolHandler* ip_hdl = IPProtocolHandler::getInstance(); in_addr netmask_addr; inet_aton((const char* )netmask,&netmask_addr); ip_hdl->add_ip_addr(ip.s_addr,netmask_addr.s_addr,this); add_protocol(ip_hdl); BOOST_LOG_TRIVIAL(debug) << ifname <<" Start Working IP"; BOOST_LOG_TRIVIAL(debug) << "Setting IP Addr " << format_ip_addr((uint8_t*)(&ip.s_addr)) << " Iface "<< ifname; }
/* Get the codename for the selected suite. */ int get_codename (void) { char *command; FILE *f = NULL; char *hostname, *directory, *suite = NULL; int ret = 1; hostname = add_protocol("hostname"); debconf_get(debconf, hostname); free(hostname); hostname = strdup(debconf->value); directory = add_protocol("directory"); debconf_get(debconf, directory); free(directory); directory = strdup(debconf->value); /* As suite has been determined previously, this should not fail */ debconf_get(debconf, DEBCONF_BASE "suite"); if (strlen(debconf->value) > 0) { suite = strdup(debconf->value); asprintf(&command, "wget -q %s://%s%s/dists/%s/Release -O - | grep ^Codename: | cut -d' ' -f 2", protocol, hostname, directory, suite); di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command); f = popen(command, "r"); free(command); if (f != NULL) { char buf[SUITE_LENGTH]; if (fgets(buf, SUITE_LENGTH - 1, f)) { if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = '\0'; debconf_set(debconf, DEBCONF_BASE "codename", buf); di_log(DI_LOG_LEVEL_INFO, "codename set to: %s", buf); ret = 0; } } pclose(f); } free(hostname); free(directory); if (suite) free(suite); if (ret != 0) di_log(DI_LOG_LEVEL_ERROR, "Error getting codename"); return ret; }
static int set_proxy(void) { char *px = add_protocol("proxy"); char *proxy_var; asprintf(&proxy_var, "%s_proxy", protocol); debconf_get(debconf, px); if (debconf->value != NULL && strlen(debconf->value)) { if (strchr(debconf->value, ':')) setenv(proxy_var, debconf->value, 1); else { char *proxy_value; asprintf(&proxy_value, "http://%s", debconf->value); setenv(proxy_var, proxy_value, 1); free(proxy_value); } } else { unsetenv(proxy_var); } free(proxy_var); free(px); return 0; }
DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { COMM_DHCP_REPLY Reply; PDHCP_ADAPTER Adapter; struct protocol* proto; ApiLock(); Adapter = AdapterFindIndex( Req->AdapterIndex ); Reply.Reply = Adapter ? 1 : 0; if( Adapter ) { proto = find_protocol_by_adapter( &Adapter->DhclientInfo ); if (proto) remove_protocol(proto); add_protocol( Adapter->DhclientInfo.name, Adapter->DhclientInfo.rfdesc, got_one, &Adapter->DhclientInfo ); Adapter->DhclientInfo.client->state = S_INIT; state_reboot(&Adapter->DhclientInfo); if (AdapterStateChangedEvent != NULL) SetEvent(AdapterStateChangedEvent); } ApiUnlock(); return Send( &Reply ); }
void icmp_startup(int routep, void (*handler)(struct iaddr, u_int8_t *, int)) { struct protoent *proto; int protocol = 1, state; /* Only initialize icmp once. */ if (icmp_protocol_initialized) error("attempted to reinitialize icmp protocol"); icmp_protocol_initialized = 1; /* Get the protocol number (should be 1). */ if ((proto = getprotobyname("icmp")) != NULL) protocol = proto->p_proto; /* Get a raw socket for the ICMP protocol. */ if ((icmp_protocol_fd = socket(AF_INET, SOCK_RAW, protocol)) == -1) error("unable to create icmp socket: %m"); /* Make sure it does routing... */ state = 0; if (setsockopt(icmp_protocol_fd, SOL_SOCKET, SO_DONTROUTE, &state, sizeof(state)) == -1) error("Unable to disable SO_DONTROUTE on ICMP socket: %m"); add_protocol("icmp", icmp_protocol_fd, icmp_echoreply, (void *)handler); }
static int choose_country(void) { if (country) free(country); country = NULL; #if defined (WITH_FTP_MANUAL) assert(protocol != NULL); if (strcasecmp(protocol,"ftp") == 0) return 0; #endif debconf_get(debconf, DEBCONF_BASE "country"); if (! strlen(debconf->value)) { /* Not set yet. Seed with a default value. */ if ((debconf_get(debconf, "debian-installer/country") == 0) && (debconf->value != NULL) ) { country = strdup (debconf->value); debconf_set(debconf, DEBCONF_BASE "country", country); } } else { country = debconf->value; } /* Ensure 'country' is set to something. */ if (country == NULL || *country == 0) { country = "GB"; } char *countries; countries = add_protocol("countries"); if (has_mirror(country)) { const char *default_country = MANUAL_ENTRY; /* TODO: duplicates much of mirrors_in and has_mirror, since * those don't let us get the country at the moment */ if (strcmp(country, MANUAL_ENTRY) != 0 && strcmp(country, MANUAL_ENTRY_OLD) != 0) { int i = 0; struct mirror_t *mirrors = mirror_list(); for (i = 0; mirrors[i].country != NULL; i++) { if (strcmp(mirrors[i].country, country) == 0 || mirrors[i].wildcard) { default_country = mirrors[i].country; break; } } } debconf_set(debconf, countries, default_country); debconf_fget(debconf, DEBCONF_BASE "country", "seen"); debconf_fset(debconf, countries, "seen", debconf->value); } debconf_input(debconf, base_on_cd ? "medium" : "high", countries); free (countries); return 0; }
static int choose_proxy(void) { char *px = add_protocol("proxy"); /* This is a nasty way to check whether we ought to have a network * connection; if we don't, it isn't worthwhile to ask for a proxy. * We should really change netcfg to write out a flag somewhere. */ if (debconf_get(debconf, "netcfg/dhcp_options") == 0 && debconf->value != NULL && strncmp(debconf->value, "Do not configure", strlen("Do not configure")) == 0) { debconf_input(debconf, "low", px); } else { debconf_input(debconf, "high", px); } free(px); return 0; }
static int set_country(void) { char *countries; #if defined (WITH_FTP_MANUAL) assert(protocol != NULL); if (strcasecmp(protocol,"ftp") == 0) return 0; #endif countries = add_protocol("countries"); debconf_get(debconf, countries); country = strdup(debconf->value); debconf_set(debconf, DEBCONF_BASE "country", country); free (countries); return 0; }
static int choose_country(void) { if (country) free(country); country = NULL; #if defined (WITH_FTP_MANUAL) assert(protocol != NULL); if (strcasecmp(protocol,"ftp") == 0) return 0; #endif debconf_get(debconf, DEBCONF_BASE "country"); if (! strlen(debconf->value)) { /* Not set yet. Seed with a default value. */ if ((debconf_get(debconf, "debian-installer/country") == 0) && (debconf->value != NULL) ) { country = strdup (debconf->value); debconf_set(debconf, DEBCONF_BASE "country", country); } } else { country = debconf->value; } /* Ensure 'country' is set to something. */ if (country == NULL || *country == 0) { country = "GB"; } char *countries; countries = add_protocol("countries"); if (has_mirror(country)) { debconf_set(debconf, countries, country); debconf_fget(debconf, DEBCONF_BASE "country", "seen"); debconf_fset(debconf, countries, "seen", debconf->value); } debconf_input(debconf, base_on_cd ? "medium" : "high", countries); free (countries); return 0; }
void udpsock_startup(struct in_addr bindaddr) { int sock, onoff; struct sockaddr_in sin4; struct udpsock *udpsock; if ((udpsock = calloc(1, sizeof(struct udpsock))) == NULL) error("could not create udpsock: %s", strerror(errno)); memset(&sin4, 0, sizeof(sin4)); if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) error("creating a socket failed for udp: %s", strerror(errno)); onoff = 1; if (setsockopt(sock, IPPROTO_IP, IP_RECVIF, &onoff, sizeof(onoff)) != 0) error("setsocketopt IP_RECVIF failed for udp: %s", strerror(errno)); if (pledge("stdio rpath inet sendfd proc id", NULL) == -1) error("pledge: %s", strerror(errno)); sin4.sin_family = AF_INET; sin4.sin_len = sizeof(sin4); sin4.sin_addr = bindaddr; sin4.sin_port = server_port; if (bind(sock, (struct sockaddr *)&sin4, sizeof(sin4)) != 0) error("bind failed for udp: %s", strerror(errno)); add_protocol("udp", sock, udpsock_handler, (void *)(intptr_t)udpsock); note("Listening on %s:%d/udp.", inet_ntoa(sin4.sin_addr), ntohs(server_port)); udpsock->sock = sock; }
static int validate_mirror(void) { char *mir; char *host; char *dir; int valid; mir = add_protocol("mirror"); host = add_protocol("hostname"); dir = add_protocol("directory"); if (! manual_entry) { char *mirror; /* * Copy information about the selected * mirror into mirror/{protocol}/{hostname,directory}, * which is the standard location other * tools can look at. */ debconf_get(debconf, mir); mirror = strdup(debconf->value); debconf_set(debconf, host, mirror); debconf_set(debconf, dir, mirror_root(mirror)); free(mirror); if (base_on_cd) { /* We have the base system on the CD, so instead of * trying to contact the mirror (which might take * some time to time out if there's no network * connection), let's just assume that the CD will * be sufficient to get a basic system up, setting * suite to PREFERRED_DISTRIBUTION if unset and * codename = suite. Note that this is an * Ubuntu-specific change since (a) Debian netinst * CDs etc. may not be able to install a complete * system from the network and (b) codename != suite * in Debian. * * We only do this for mirrors in our mirror list, * since we assume that those have a good chance of * not being typoed. For manually-entered mirrors, * we still do full mirror validation. */ di_log(DI_LOG_LEVEL_INFO, "base system installable from CD; skipping mirror check"); debconf_get(debconf, DEBCONF_BASE "suite"); if (!*debconf->value) { di_log(DI_LOG_LEVEL_INFO, "falling back to suite %s", PREFERRED_DISTRIBUTION); debconf_set(debconf, DEBCONF_BASE "suite", PREFERRED_DISTRIBUTION); } debconf_get(debconf, DEBCONF_BASE "suite"); di_log(DI_LOG_LEVEL_INFO, "falling back to codename %s", debconf->value); debconf_set(debconf, DEBCONF_BASE "codename", debconf->value); exit(0); } valid = find_suite(); } else { /* check to see if the entered data is basically ok */ int ok = 1; debconf_get(debconf, host); if (debconf->value == NULL || strcmp(debconf->value, "") == 0 || strchr(debconf->value, '/') != NULL) { ok = 0; } debconf_get(debconf, dir); if (debconf->value == NULL || strcmp(debconf->value, "") == 0) { ok = 0; } if (ok) { valid = find_suite(); } else { valid = 0; } } free(mir); free(host); free(dir); if (valid) { return 0; } else { debconf_input(debconf, "critical", DEBCONF_BASE "bad"); if (debconf_go(debconf) == 30) exit(10); /* back up to menu */ else return 1; /* back to beginning of questions */ } }
/* * Fetch a Release file, extract its Suite and Codename and check its valitity. */ static int get_release(struct release_t *release, const char *name) { char *command; FILE *f = NULL; char *hostname, *directory; char line[80]; char buf[SUITE_LENGTH]; if (base_on_cd && ! manual_entry) { /* We have the base system on the CD, so instead of trying * to contact the mirror (which might take some time to time * out if there's no network connection), let's just assume * that the CD will be sufficient to get a basic system up, * setting codename = suite. Note that this is an * Ubuntu-specific change since (a) Debian netinst CDs etc. * may not be able to install a complete system from the * network and (b) codename != suite in Debian. * * We only do this for mirrors in our mirror list, since we * assume that those have a good chance of not being typoed. * For manually-entered mirrors, we still do full mirror * validation. */ di_log(DI_LOG_LEVEL_INFO, "base system installable from CD; skipping mirror check"); release->name = strdup(name); release->suite = strdup(name); release->status = IS_VALID | GET_CODENAME; return 1; } hostname = add_protocol("hostname"); debconf_get(debconf, hostname); free(hostname); hostname = strdup(debconf->value); directory = add_protocol("directory"); debconf_get(debconf, directory); free(directory); directory = strdup(debconf->value); asprintf(&command, "wget -q %s://%s%s/dists/%s/Release -O - | grep -E '^(Suite|Codename):'", protocol, hostname, directory, name); di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command); f = popen(command, "r"); free(command); free(hostname); free(directory); if (f != NULL) { while (fgets(line, sizeof(line), f) != NULL) { char *value; if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; if ((value = strstr(line, ": ")) != NULL) { strncpy(buf, value + 2, SUITE_LENGTH - 1); buf[SUITE_LENGTH - 1] = '\0'; if (strncmp(line, "Codename:", 9) == 0) release->name = strdup(buf); if (strncmp(line, "Suite:", 6) == 0) release->suite = strdup(buf); } } if (release->name != NULL && strcmp(release->name, name) == 0) release->status |= IS_VALID | GET_CODENAME; if (release->suite != NULL && strcmp(release->suite, name) == 0) release->status |= IS_VALID | GET_SUITE; if ((release->name != NULL || release->suite != NULL) && !(release->status & IS_VALID)) log_invalid_release(name, "Suite or Codename"); /* Cross-validate the Release file */ if (release->status & IS_VALID) if (! cross_validate_release(release)) log_invalid_release(name, (release->status & GET_SUITE) ? "Codename" : "Suite"); /* In case there is no Codename field */ if ((release->status & IS_VALID) && release->name == NULL) release->name = strdup(name); // di_log(DI_LOG_LEVEL_DEBUG, "get_release(): %s -> %s:%s (0x%x)", // name, release->suite, release->name, release->status); } pclose(f); if (release->name != NULL) { return 1; } else { free(release->suite); return 0; } }
/* * XXX Figure out the way to bind a specific adapter to a socket. */ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) { PMIB_IFTABLE Table = (PMIB_IFTABLE) malloc(sizeof(MIB_IFTABLE)); DWORD Error, Size = sizeof(MIB_IFTABLE); PDHCP_ADAPTER Adapter = NULL; HANDLE AdapterStateChangedEvent = (HANDLE)Context; struct interface_info *ifi = NULL; struct protocol *proto; int i, AdapterCount = 0, Broadcast; /* FIXME: Kill this thread when the service is stopped */ do { DH_DbgPrint(MID_TRACE,("Getting Adapter List...\n")); while( (Error = GetIfTable(Table, &Size, 0 )) == ERROR_INSUFFICIENT_BUFFER ) { DH_DbgPrint(MID_TRACE,("Error %d, New Buffer Size: %d\n", Error, Size)); free( Table ); Table = (PMIB_IFTABLE) malloc( Size ); } if( Error != NO_ERROR ) { /* HACK: We are waiting until TCP/IP starts */ Sleep(2000); continue; } DH_DbgPrint(MID_TRACE,("Got Adapter List (%d entries)\n", Table->dwNumEntries)); for( i = Table->dwNumEntries - 1; i >= 0; i-- ) { DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n", Table->table[i].dwIndex)); ApiLock(); if ((Adapter = AdapterFindByHardwareAddress(Table->table[i].bPhysAddr, Table->table[i].dwPhysAddrLen))) { proto = find_protocol_by_adapter(&Adapter->DhclientInfo); /* This is an existing adapter */ if (InterfaceConnected(&Table->table[i])) { /* We're still active so we stay in the list */ ifi = &Adapter->DhclientInfo; /* This is a hack because IP helper API sucks */ if (IsReconnectHackNeeded(Adapter, &Table->table[i])) { /* This handles a disconnect/reconnect */ if (proto) remove_protocol(proto); Adapter->DhclientInfo.client->state = S_INIT; /* These are already invalid since the media state change */ Adapter->RouterMib.dwForwardNextHop = 0; Adapter->NteContext = 0; add_protocol(Adapter->DhclientInfo.name, Adapter->DhclientInfo.rfdesc, got_one, &Adapter->DhclientInfo); state_init(&Adapter->DhclientInfo); SetEvent(AdapterStateChangedEvent); } } else { if (proto) remove_protocol(proto); /* We've lost our link so out we go */ RemoveEntryList(&Adapter->ListEntry); free(Adapter); } ApiUnlock(); continue; } ApiUnlock(); Adapter = (DHCP_ADAPTER*) calloc( sizeof( DHCP_ADAPTER ) + Table->table[i].dwMtu, 1 ); if( Adapter && Table->table[i].dwType == MIB_IF_TYPE_ETHERNET && InterfaceConnected(&Table->table[i])) { memcpy( &Adapter->IfMib, &Table->table[i], sizeof(Adapter->IfMib) ); Adapter->DhclientInfo.client = &Adapter->DhclientState; Adapter->DhclientInfo.rbuf = Adapter->recv_buf; Adapter->DhclientInfo.rbuf_max = Table->table[i].dwMtu; Adapter->DhclientInfo.rbuf_len = Adapter->DhclientInfo.rbuf_offset = 0; memcpy(Adapter->DhclientInfo.hw_address.haddr, Adapter->IfMib.bPhysAddr, Adapter->IfMib.dwPhysAddrLen); Adapter->DhclientInfo.hw_address.hlen = Adapter->IfMib.dwPhysAddrLen; /* I'm not sure where else to set this, but some DHCP servers won't take a zero. We checked the hardware type earlier in the if statement. */ Adapter->DhclientInfo.hw_address.htype = HTYPE_ETHER; if( DhcpSocket == INVALID_SOCKET ) { DhcpSocket = Adapter->DhclientInfo.rfdesc = Adapter->DhclientInfo.wfdesc = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if (DhcpSocket != INVALID_SOCKET) { /* Allow broadcast on this socket */ Broadcast = 1; setsockopt(DhcpSocket, SOL_SOCKET, SO_BROADCAST, (const char *)&Broadcast, sizeof(Broadcast)); Adapter->ListenAddr.sin_family = AF_INET; Adapter->ListenAddr.sin_port = htons(LOCAL_PORT); Adapter->BindStatus = (bind( Adapter->DhclientInfo.rfdesc, (struct sockaddr *)&Adapter->ListenAddr, sizeof(Adapter->ListenAddr) ) == 0) ? 0 : WSAGetLastError(); } else { error("socket() failed: %d\n", WSAGetLastError()); } } else { Adapter->DhclientInfo.rfdesc = Adapter->DhclientInfo.wfdesc = DhcpSocket; } Adapter->DhclientConfig.timeout = DHCP_PANIC_TIMEOUT; Adapter->DhclientConfig.initial_interval = DHCP_DISCOVER_INTERVAL; Adapter->DhclientConfig.retry_interval = DHCP_DISCOVER_INTERVAL; Adapter->DhclientConfig.select_interval = 1; Adapter->DhclientConfig.reboot_timeout = DHCP_REBOOT_TIMEOUT; Adapter->DhclientConfig.backoff_cutoff = DHCP_BACKOFF_MAX; Adapter->DhclientState.interval = Adapter->DhclientConfig.retry_interval; if( PrepareAdapterForService( Adapter ) ) { Adapter->DhclientInfo.next = ifi; ifi = &Adapter->DhclientInfo; read_client_conf(&Adapter->DhclientInfo); if (Adapter->DhclientInfo.client->state == S_INIT) { add_protocol(Adapter->DhclientInfo.name, Adapter->DhclientInfo.rfdesc, got_one, &Adapter->DhclientInfo); state_init(&Adapter->DhclientInfo); } ApiLock(); InsertTailList( &AdapterList, &Adapter->ListEntry ); AdapterCount++; SetEvent(AdapterStateChangedEvent); ApiUnlock(); } else { free( Adapter ); Adapter = 0; } } else { free( Adapter ); Adapter = 0; } if( !Adapter ) DH_DbgPrint(MID_TRACE,("Adapter %d was rejected\n", Table->table[i].dwIndex)); } #if 0 Error = NotifyAddrChange(NULL, NULL); if (Error != NO_ERROR) break; #else Sleep(3000); #endif } while (TRUE); DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error); if( Table ) free( Table ); return Error; }
int main(int argc, char *argv[]) { int ch, no_daemon = 0, opt, rdomain; extern char *__progname; struct server_list *sp = NULL; struct passwd *pw; struct sockaddr_in laddr; /* Initially, log errors to stderr as well as to syslogd. */ openlog(__progname, LOG_NDELAY, DHCPD_LOG_FACILITY); setlogmask(LOG_UPTO(LOG_INFO)); while ((ch = getopt(argc, argv, "adi:o")) != -1) { switch (ch) { case 'd': no_daemon = 1; break; case 'i': if (interfaces != NULL) usage(); if ((interfaces = calloc(1, sizeof(struct interface_info))) == NULL) error("calloc"); strlcpy(interfaces->name, optarg, sizeof(interfaces->name)); break; case 'o': /* add the relay agent information option */ oflag++; break; default: usage(); /* not reached */ } } argc -= optind; argv += optind; if (argc < 1) usage(); while (argc > 0) { struct hostent *he; struct in_addr ia, *iap = NULL; if (inet_aton(argv[0], &ia)) iap = &ia; else { he = gethostbyname(argv[0]); if (!he) warning("%s: host unknown", argv[0]); else iap = ((struct in_addr *)he->h_addr_list[0]); } if (iap) { if ((sp = calloc(1, sizeof *sp)) == NULL) error("calloc"); sp->next = servers; servers = sp; memcpy(&sp->to.sin_addr, iap, sizeof *iap); } argc--; argv++; } if (!no_daemon) log_perror = 0; if (interfaces == NULL) error("no interface given"); /* Default DHCP/BOOTP ports. */ server_port = htons(SERVER_PORT); client_port = htons(CLIENT_PORT); /* We need at least one server. */ if (!sp) usage(); discover_interfaces(interfaces); rdomain = get_rdomain(interfaces->name); /* Enable the relay agent option by default for enc0 */ if (interfaces->hw_address.htype == HTYPE_IPSEC_TUNNEL) oflag++; bzero(&laddr, sizeof laddr); laddr.sin_len = sizeof laddr; laddr.sin_family = AF_INET; laddr.sin_port = server_port; laddr.sin_addr.s_addr = interfaces->primary_address.s_addr; /* Set up the server sockaddrs. */ for (sp = servers; sp; sp = sp->next) { sp->to.sin_port = server_port; sp->to.sin_family = AF_INET; sp->to.sin_len = sizeof sp->to; sp->fd = socket(AF_INET, SOCK_DGRAM, 0); if (sp->fd == -1) error("socket: %m"); opt = 1; if (setsockopt(sp->fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) == -1) error("setsockopt: %m"); if (setsockopt(sp->fd, SOL_SOCKET, SO_RTABLE, &rdomain, sizeof(rdomain)) == -1) error("setsockopt: %m"); if (bind(sp->fd, (struct sockaddr *)&laddr, sizeof laddr) == -1) error("bind: %m"); if (connect(sp->fd, (struct sockaddr *)&sp->to, sizeof sp->to) == -1) error("connect: %m"); add_protocol("server", sp->fd, got_response, sp); } /* Socket used to forward packets to the DHCP client */ if (interfaces->hw_address.htype == HTYPE_IPSEC_TUNNEL) { laddr.sin_addr.s_addr = INADDR_ANY; server_fd = socket(AF_INET, SOCK_DGRAM, 0); if (server_fd == -1) error("socket: %m"); opt = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) == -1) error("setsockopt: %m"); if (setsockopt(server_fd, SOL_SOCKET, SO_RTABLE, &rdomain, sizeof(rdomain)) == -1) error("setsockopt: %m"); if (bind(server_fd, (struct sockaddr *)&laddr, sizeof(laddr)) == -1) error("bind: %m"); } tzset(); time(&cur_time); bootp_packet_handler = relay; if (!no_daemon) daemon(0, 0); if ((pw = getpwnam("_dhcp")) == NULL) error("user \"_dhcp\" not found"); if (chroot(_PATH_VAREMPTY) == -1) error("chroot: %m"); if (chdir("/") == -1) error("chdir(\"/\"): %m"); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) error("can't drop privileges: %m"); dispatch(); /* not reached */ exit(0); }
void discover_interfaces(int *rdomain) { struct interface_info *tmp; struct interface_info *last, *next; struct subnet *subnet; struct shared_network *share; struct sockaddr_in foo; int ir = 0, ird; struct ifreq *tif; struct ifaddrs *ifap, *ifa; if (getifaddrs(&ifap) != 0) error("getifaddrs failed"); /* * If we already have a list of interfaces, the interfaces were * requested. */ if (interfaces != NULL) ir = 1; else /* must specify an interface when rdomains are used */ *rdomain = 0; /* Cycle through the list of interfaces looking for IP addresses. */ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { /* * See if this is the sort of interface we want to * deal with. 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 ((ifa->ifa_flags & IFF_LOOPBACK) || (ifa->ifa_flags & IFF_POINTOPOINT) || (!(ifa->ifa_flags & IFF_UP)) || (!(ifa->ifa_flags & IFF_BROADCAST))) continue; /* See if we've seen an interface that matches this one. */ for (tmp = interfaces; tmp; tmp = tmp->next) if (!strcmp(tmp->name, ifa->ifa_name)) break; /* If we are looking for specific interfaces, ignore others. */ if (tmp == NULL && ir) continue; ird = get_rdomain(ifa->ifa_name); if (*rdomain == -1) *rdomain = ird; else if (*rdomain != ird && ir) error("Interface %s is not in rdomain %d", tmp->name, *rdomain); else if (*rdomain != ird && !ir) continue; /* If there isn't already an interface by this name, allocate one. */ if (tmp == NULL) { tmp = calloc(1, sizeof *tmp); if (!tmp) error("Insufficient memory to %s %s", "record interface", ifa->ifa_name); strlcpy(tmp->name, ifa->ifa_name, sizeof(tmp->name)); tmp->next = interfaces; tmp->noifmedia = tmp->dead = tmp->errors = 0; interfaces = tmp; } /* If we have the capability, extract link information and record it in a linked list. */ if (ifa->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl *foo = ((struct sockaddr_dl *)(ifa->ifa_addr)); tmp->index = foo->sdl_index; tmp->hw_address.hlen = foo->sdl_alen; tmp->hw_address.htype = HTYPE_ETHER; /* XXX */ memcpy(tmp->hw_address.haddr, LLADDR(foo), foo->sdl_alen); } else if (ifa->ifa_addr->sa_family == AF_INET) { struct iaddr addr; /* Get a pointer to the address... */ memcpy(&foo, ifa->ifa_addr, sizeof(foo)); /* 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) { int len = (IFNAMSIZ + ifa->ifa_addr->sa_len); tif = (struct ifreq *)malloc(len); if (!tif) error("no space to remember ifp."); strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ); memcpy(&tif->ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_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) { warning("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) { warning("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) { warning("Multiple %s %s: %s %s", "interfaces match the", "same shared network", share->interface->name, tmp->name); } } } } /* Discard interfaces we can't listen on. */ last = NULL; for (tmp = interfaces; tmp; tmp = next) { next = tmp->next; if (!tmp->ifp) { warning("Can't listen on %s - it has no IP address.", tmp->name); /* Remove tmp from the list of interfaces. */ if (!last) interfaces = interfaces->next; else last->next = tmp->next; continue; } memcpy(&foo, &tmp->ifp->ifr_addr, sizeof tmp->ifp->ifr_addr); if (!tmp->shared_network) { warning("Can't listen on %s - dhcpd.conf has no subnet " "declaration for %s.", tmp->name, inet_ntoa(foo.sin_addr)); /* Remove tmp from the list of interfaces. */ if (!last) interfaces = interfaces->next; else last->next = tmp->next; continue; } last = tmp; /* Find subnets that don't have valid interface addresses. */ for (subnet = (tmp->shared_network ? tmp->shared_network->subnets : NULL); 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); note("Listening on %s (%s).", tmp->name, inet_ntoa(foo.sin_addr)); } if (interfaces == NULL) error("No interfaces to listen on."); /* Now register all the remaining interfaces as protocols. */ for (tmp = interfaces; tmp; tmp = tmp->next) add_protocol(tmp->name, tmp->rfdesc, got_one, tmp); freeifaddrs(ifap); }
/* * Use getifaddrs() 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(struct interface_info *iface) { struct ifaddrs *ifap, *ifa; struct sockaddr_in foo; struct ifreq *tif; if (getifaddrs(&ifap) != 0) error("getifaddrs failed"); for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if ((ifa->ifa_flags & IFF_LOOPBACK) || (ifa->ifa_flags & IFF_POINTOPOINT) || (!(ifa->ifa_flags & IFF_UP))) continue; if (strcmp(iface->name, ifa->ifa_name)) continue; /* * If we have the capability, extract link information * and record it in a linked list. */ if (ifa->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl *foo = (struct sockaddr_dl *)ifa->ifa_addr; iface->index = foo->sdl_index; iface->hw_address.hlen = foo->sdl_alen; iface->hw_address.htype = HTYPE_ETHER; /* XXX */ memcpy(iface->hw_address.haddr, LLADDR(foo), foo->sdl_alen); } else if (ifa->ifa_addr->sa_family == AF_INET) { struct iaddr addr; memcpy(&foo, ifa->ifa_addr, sizeof(foo)); if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) continue; if (!iface->ifp) { int len = IFNAMSIZ + ifa->ifa_addr->sa_len; if ((tif = malloc(len)) == NULL) error("no space to remember ifp"); strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ); memcpy(&tif->ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); iface->ifp = tif; iface->primary_address = foo.sin_addr; } addr.len = 4; memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len); } } if (!iface->ifp) error("%s: not found", iface->name); /* Register the interface... */ if_register_receive(iface); if_register_send(iface); add_protocol(iface->name, iface->rfdesc, got_one, iface); freeifaddrs(ifap); }
/* * Using the current debconf settings for a mirror, figure out which suite * to use from the mirror and set mirror/suite. * * This is accomplished by downloading the Release file from the mirror. * Suite selection tries each suite in turn, and stops at the first one that * seems usable. * * If no Release file is found, returns false. That probably means the * mirror is broken or unreachable. */ int find_suite (void) { char *command; FILE *f = NULL; char *hostname, *directory; int nbr_suites = sizeof(suites)/SUITE_LENGTH; int i; int ret = 0; char buf[SUITE_LENGTH]; if (show_progress) { debconf_progress_start(debconf, 0, 1, DEBCONF_BASE "checking_title"); debconf_progress_info(debconf, DEBCONF_BASE "checking_download"); } hostname = add_protocol("hostname"); debconf_get(debconf, hostname); free(hostname); hostname = strdup(debconf->value); directory = add_protocol("directory"); debconf_get(debconf, directory); free(directory); directory = strdup(debconf->value); /* Try each suite in turn until one is found that works. */ for (i=0; i <= nbr_suites && ! ret; i++) { char *suite; if (i == 0) { /* First check for a preseeded suite. */ debconf_get(debconf, DEBCONF_BASE "suite"); if (strlen(debconf->value) > 0) { suite = strdup(debconf->value); } else { /* Read this file to find the default suite * to use. */ f = fopen("/etc/default-release", "r"); if (f != NULL) { if (fgets(buf, SUITE_LENGTH - 1, f)) { if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = '\0'; suite = strdup(buf); fclose(f); } else { fclose(f); continue; } } else { continue; } } } else { suite = strdup(suites[i - 1]); } asprintf(&command, "wget -q %s://%s%s/dists/%s/Release -O - | grep ^Suite: | cut -d' ' -f 2", protocol, hostname, directory, suite); di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command); f = popen(command, "r"); free(command); if (f != NULL) { if (fgets(buf, SUITE_LENGTH - 1, f)) { if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = '\0'; debconf_set(debconf, DEBCONF_BASE "suite", buf); ret = 1; } } pclose(f); free(suite); } free(hostname); free(directory); if (show_progress) { debconf_progress_step(debconf, 1); debconf_progress_stop(debconf); } return ret; }