1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Copyright (c) 2006-2010 Roy Marples <roy@marples.name> 4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * All rights reserved 5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Redistribution and use in source and binary forms, with or without 7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * modification, are permitted provided that the following conditions 8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * are met: 9f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 10f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer. 11f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 12f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * documentation and/or other materials provided with the distribution. 14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * SUCH DAMAGE. 26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 28e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconst char copyright[] = "Copyright (c) 2006-2010 Roy Marples"; 29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/file.h> 31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/socket.h> 32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/stat.h> 33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/time.h> 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/types.h> 35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/uio.h> 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <arpa/inet.h> 38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <net/route.h> 39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef __linux__ 41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <asm/types.h> /* for systems with broken headers */ 42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt# include <linux/rtnetlink.h> 43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <ctype.h> 46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <getopt.h> 48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <limits.h> 49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <paths.h> 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <signal.h> 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h> 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h> 54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <time.h> 57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "arp.h" 59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "bind.h" 60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h" 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "configure.h" 63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "control.h" 64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcpcd.h" 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "duid.h" 66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h" 67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h" 68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-pref.h" 69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "ipv4ll.h" 70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "net.h" 71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "signals.h" 72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 730545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 740545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <linux/capability.h> 750545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <linux/prctl.h> 760545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <cutils/properties.h> 770545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#include <private/android_filesystem_config.h> 780545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 790545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt 80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* We should define a maximum for the NAK exponential backoff */ 81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define NAKOFF_MAX 60 82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Wait N nanoseconds between sending a RELEASE and dropping the address. 84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This gives the kernel enough time to actually send it. */ 85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define RELEASE_DELAY_S 0 86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define RELEASE_DELAY_NS 10000000 87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint options = 0; 89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint pidfd = -1; 90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct interface *ifaces = NULL; 91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint ifac = 0; 92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtchar **ifav = NULL; 93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint ifdc = 0; 94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtchar **ifdv = NULL; 950d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync/* If set, avoid routes after a DHCP success */ 960d3a47d979ac35a49b2a2da9e80e16bd37aab877repo syncint avoid_routes = 0; 97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char **margv; 99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int margc; 100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct if_options *if_options; 101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char **ifv; 102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int ifc; 103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char *cffile; 104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic char *pidfile; 105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int linkfd = -1; 106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct dhcp_op { 108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t value; 109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char *name; 110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const struct dhcp_op dhcp_ops[] = { 113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_DISCOVER, "DISCOVER" }, 114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_OFFER, "OFFER" }, 115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_REQUEST, "REQUEST" }, 116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_DECLINE, "DECLINE" }, 117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_ACK, "ACK" }, 118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_NAK, "NAK" }, 119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_RELEASE, "RELEASE" }, 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { DHCP_INFORM, "INFORM" }, 121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 0, NULL } 122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}; 123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void send_release(struct interface *); 125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const char * 127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_dhcp_op(uint8_t type) 128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct dhcp_op *d; 130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (d = dhcp_ops; d->name; d++) 132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (d->value == type) 133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return d->name; 134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 137f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic pid_t 138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtread_pid(void) 139f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project FILE *fp; 141938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt pid_t pid; 142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((fp = fopen(pidfile, "r")) == NULL) { 144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOENT; 145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 147938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (fscanf(fp, "%d", &pid) != 1) 148938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt pid = 0; 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fclose(fp); 150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return pid; 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic void 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectusage(void) 155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1560d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync printf("usage: "PACKAGE" [-adgknpqwxyADEGHJKLOTV] [-c script] [-f file]" 157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-e var=val]\n" 158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-h hostname] [-i classID ] [-l leasetime]" 159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-m metric] [-o option]\n" 160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-r ipaddr] [-s ipaddr] [-t timeout]" 161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-u userclass]\n" 162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-F none|ptr|both] [-I clientID] [-C hookscript]" 163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-Q option]\n" 164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " [-X ipaddr] <interface>\n"); 165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtcleanup(void) 169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface; 172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int i; 173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_options(if_options); 175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (ifaces) { 177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface = ifaces; 178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifaces = iface->next; 179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(iface); 180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifac; i++) 183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifav[i]); 184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifav); 185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifdc; i++) 186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifdv[i]); 187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifdv); 188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (linkfd != -1) 191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(linkfd); 192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (pidfd > -1) { 193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_MASTER) { 194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (stop_control() == -1) 195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "stop_control: %m"); 196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(pidfd); 198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unlink(pidfile); 199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(pidfile); 202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */ 206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_exit_timeout(_unused void *arg) 208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int timeout; 210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "timed out"); 212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_TIMEOUT_IPV4LL)) { 213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_MASTER) { 214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt daemonise(); 215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options &= ~DHCPCD_TIMEOUT_IPV4LL; 220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeout = (PROBE_NUM * PROBE_MAX) + PROBE_WAIT + 1; 221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout); 222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(timeout, handle_exit_timeout, NULL); 223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdrop_config(struct interface *iface, const char *reason) 227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->old); 229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->old = iface->state->new; 230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new = NULL; 231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->reason = reason; 232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure(iface); 233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->old); 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->old = NULL; 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.addr.s_addr = 0; 236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstruct interface * 239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfind_interface(const char *ifname) 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp; 242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifp->name, ifname) == 0) 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return ifp; 246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return NULL; 247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstop_interface(struct interface *iface) 251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp, *ifl = NULL; 253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: removing interface", iface->name); 255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(iface->state->reason, "RELEASE") != 0) 256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "STOP"); 257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) { 260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp == iface) 261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifp; 263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifl) 265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl->next = ifp->next; 266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifaces = ifp->next; 268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(ifp); 269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic uint32_t 274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdhcp_xid(struct interface *iface) 275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint32_t xid; 277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->options->options & DHCPCD_XID_HWADDR && 279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->hwlen >= sizeof(xid)) 280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* The lower bits are probably more unique on the network */ 281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&xid, (iface->hwaddr + iface->hwlen) - sizeof(xid), 282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(xid)); 283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt xid = arc4random(); 285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return xid; 287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_message(struct interface *iface, int type, 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt void (*callback)(void *)) 292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_state *state = iface->state; 294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = state->options; 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp; 296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *udp; 297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t len, r; 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr from, to; 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt in_addr_t a = 0; 300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval tv; 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!callback) 303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: sending %s with xid 0x%x", 304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, get_dhcp_op(type), state->xid); 305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (state->interval == 0) 307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->interval = 4; 308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->interval *= 2; 310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (state->interval > 64) 311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->interval = 64; 312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tv.tv_sec = state->interval + DHCP_RAND_MIN; 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tv.tv_usec = arc4random() % (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U); 315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, 316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: sending %s (xid 0x%x), next in %0.2f seconds", 317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, get_dhcp_op(type), state->xid, 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeval_to_double(&tv)); 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure sockets are open. */ 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt open_sockets(iface); 323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we couldn't open a UDP port for our IP address 325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * then we cannot renew. 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This could happen if our IP was pulled out from underneath us. 327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Also, we should not unicast from a BOOTP lease. */ 328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->udp_fd == -1 || 329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (!(ifo->options & DHCPCD_INFORM) && is_bootp(iface->state->new))) 330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt a = iface->addr.s_addr; 332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr = 0; 333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = make_message(&dhcp, iface, type); 335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (a) 336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr = a; 337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt from.s_addr = dhcp->ciaddr; 338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (from.s_addr) 339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt to.s_addr = state->lease.server.s_addr; 340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt to.s_addr = 0; 342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (to.s_addr && to.s_addr != INADDR_BROADCAST) { 343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = send_packet(iface, to, (uint8_t *)dhcp, len); 344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r == -1) { 345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: send_packet: %m", iface->name); 346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = make_udp_packet(&udp, (uint8_t *)dhcp, len, from, to); 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = send_raw_packet(iface, ETHERTYPE_IP, udp, len); 351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(udp); 352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we failed to send a raw packet this normally means 353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * we don't have the ability to work beneath the IP layer 354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * for this interface. 355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * As such we remove it from consideration without actually 356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * stopping the interface. */ 357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r == -1) { 358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: send_raw_packet: %m", iface->name); 359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_TEST)) 360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "FAIL"); 361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt callback = NULL; 364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(dhcp); 367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Even if we fail to send a packet we should continue as we are 369e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * as our failure timeouts will change out codepath when needed. */ 370e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (callback) 371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_tv(&tv, callback, iface); 372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_inform(void *arg) 376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message((struct interface *)arg, DHCP_INFORM, send_inform); 378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_discover(void *arg) 382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message((struct interface *)arg, DHCP_DISCOVER, send_discover); 384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_request(void *arg) 388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message((struct interface *)arg, DHCP_REQUEST, send_request); 390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_renew(void *arg) 394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message((struct interface *)arg, DHCP_REQUEST, send_renew); 396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_rebind(void *arg) 400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message((struct interface *)arg, DHCP_REQUEST, send_rebind); 402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_expire(void *arg) 406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->interval = 0; 410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->addr.s_addr == 0) { 411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We failed to reboot, so enter discovery. */ 412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.addr.s_addr = 0; 413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_discover(iface); 414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 416e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: lease expired", iface->name); 418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "EXPIRE"); 420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unlink(iface->leasefile); 421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->carrier != LINK_DOWN) 422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(iface); 423e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtlog_dhcp(int lvl, const char *msg, 427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct interface *iface, const struct dhcp_message *dhcp, 428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct in_addr *from) 429e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 430e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char *tfrom; 431e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *a; 432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr addr; 433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int r; 434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 435e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(msg, "NAK:") == 0) 436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt a = get_option_string(dhcp, DHO_MESSAGE); 437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (dhcp->yiaddr != 0) { 438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr.s_addr = dhcp->yiaddr; 439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt a = xstrdup(inet_ntoa(addr)); 440e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt a = NULL; 442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tfrom = "from"; 444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt r = get_option_addr(&addr, dhcp, DHO_SERVERID); 445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->servername[0] && r == 0) 446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(lvl, "%s: %s %s %s %s `%s'", iface->name, msg, a, 447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tfrom, inet_ntoa(addr), dhcp->servername); 448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (r != 0) { 450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tfrom = "via"; 451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = *from; 452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (a == NULL) 454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(lvl, "%s: %s %s %s", 455e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, msg, tfrom, inet_ntoa(addr)); 456e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 457e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(lvl, "%s: %s %s %s %s", 458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, msg, a, tfrom, inet_ntoa(addr)); 459e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 460e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(a); 461e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtblacklisted_ip(const struct if_options *ifo, in_addr_t addr) 465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t i; 467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifo->blacklist_len; i += 2) 469e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->blacklist[i] == (addr & ifo->blacklist[i + 1])) 470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtwhitelisted_ip(const struct if_options *ifo, in_addr_t addr) 476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t i; 478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->whitelist_len == 0) 480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 481e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifo->whitelist_len; i += 2) 482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->whitelist[i] == (addr & ifo->whitelist[i + 1])) 483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_dhcp(struct interface *iface, struct dhcp_message **dhcpp, const struct in_addr *from) 489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_state *state = iface->state; 491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = state->options; 492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp = *dhcpp; 493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_lease *lease = &state->lease; 494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t type, tmp; 495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr addr; 496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t i; 497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* reset the message counter */ 499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->interval = 0; 500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We may have found a BOOTP server */ 502e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint8(&type, dhcp, DHO_MESSAGETYPE) == -1) 503e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt type = 0; 504e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 505e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_NAK) { 506e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* For NAK, only check if we require the ServerID */ 507e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_option_mask(ifo->requiremask, DHO_SERVERID) && 508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_option_addr(&addr, dhcp, DHO_SERVERID) == -1) 509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 510e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_WARNING, "reject NAK", iface, dhcp, from); 511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We should restart on a NAK */ 514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_WARNING, "NAK:", iface, dhcp, from); 515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_TEST)) { 516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "NAK"); 517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unlink(iface->leasefile); 518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we constantly get NAKS then we should slowly back off */ 521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(state->nakoff, start_interface, iface); 522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->nakoff *= 2; 523e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (state->nakoff > NAKOFF_MAX) 524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->nakoff = NAKOFF_MAX; 525e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 526e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 527e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 528e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure that all required options are present */ 529e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 1; i < 255; i++) { 530e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_option_mask(ifo->requiremask, i) && 531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_option_uint8(&tmp, dhcp, i) != 0) 532e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we are bootp, then ignore the need for serverid. 534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * To ignore bootp, require dhcp_message_type instead. */ 535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == 0 && i == DHO_SERVERID) 536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from); 538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 539e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 540e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* No NAK, so reset the backoff */ 543e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->nakoff = 1; 544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((type == 0 || type == DHCP_OFFER) && 546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->state == DHS_DISCOVER) 547e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->frominfo = 0; 549e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr = dhcp->yiaddr; 550e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->cookie = dhcp->cookie; 551e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == 0 || 552e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0) 553e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->server.s_addr = INADDR_ANY; 554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_INFO, "offered", iface, dhcp, from); 555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(state->offer); 556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->offer = dhcp; 557e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *dhcpp = NULL; 558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_TEST) { 559e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(state->old); 560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->old = state->new; 561e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->new = state->offer; 562e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->offer = NULL; 563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->reason = "TEST"; 564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(send_discover, iface); 568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We don't request BOOTP addresses */ 569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type) { 570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We used to ARP check here, but that seems to be in 571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * violation of RFC2131 where it only describes 572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DECLINE after REQUEST. 573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * It also seems that some MS DHCP servers actually 574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ignore DECLINE if no REQUEST, ie we decline a 575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DISCOVER. */ 576e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_request(iface); 577e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 579e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 580e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 581e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type) { 582e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_OFFER) { 583e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_INFO, "ignoring offer of", 584e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface, dhcp, from); 585e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 587e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We should only be dealing with acks */ 589e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type != DHCP_ACK) { 590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_ERR, "not ACK or OFFER", 591e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface, dhcp, from); 592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 593e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 594e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 595e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & DHCPCD_INFORM)) 596e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt log_dhcp(LOG_INFO, "acknowledged", iface, dhcp, from); 597e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 598e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 599e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* BOOTP could have already assigned this above, so check we still 600e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * have a pointer. */ 601e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (*dhcpp) { 602e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(state->offer); 603e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->offer = dhcp; 604e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *dhcpp = NULL; 605e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 606e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 607e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->frominfo = 0; 608e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 609e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 610e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We now have an offer, so close the DHCP sockets. 611e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This allows us to safely ARP when broken DHCP servers send an ACK 612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * follows by an invalid NAK. */ 613e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 614e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 615e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_ARP && 616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr != state->offer->yiaddr) 617e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 618e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If the interface already has the address configured 619e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * then we can't ARP for duplicate detection. */ 620e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr.s_addr = state->offer->yiaddr; 621e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_address(iface->name, &addr, NULL) != 1) { 622e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->claims = 0; 623e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->probes = 0; 624e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->conflicts = 0; 625e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt state->state = DHS_PROBE; 626e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_arp_probe(iface); 627e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bind_interface(iface); 632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 634e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 635e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_dhcp_packet(void *arg) 636e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 637e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 638e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *packet; 639e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp = NULL; 640e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const uint8_t *pp; 641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t bytes; 642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr from; 643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int i; 644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We loop through until our buffer is empty. 646e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * The benefit is that if we get >1 DHCP packet in our buffer and 647e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * the first one fails for any reason, we can use the next. */ 648e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt packet = xmalloc(udp_dhcp_len); 649e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for(;;) { 650e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes = get_raw_packet(iface, ETHERTYPE_IP, 651e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt packet, udp_dhcp_len); 652e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (bytes == 0 || bytes == -1) 653e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 654e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (valid_udp_packet(packet, bytes, &from) == -1) { 655e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: invalid UDP packet from %s", 656e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(from)); 657e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 658e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 659e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt i = whitelisted_ip(iface->state->options, from.s_addr); 660e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i == 0) { 661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: non whitelisted DHCP packet from %s", 663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(from)); 664e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (i != 1 && 666e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt blacklisted_ip(iface->state->options, from.s_addr) == 1) 667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 669e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: blacklisted DHCP packet from %s", 670e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(from)); 671e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 672e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 673e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->flags & IFF_POINTOPOINT && 674e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->dst.s_addr != from.s_addr) 675e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 676e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 677e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: server %s is not destination", 678e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(from)); 679e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 680e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes = get_udp_data(&pp, packet); 681e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((size_t)bytes > sizeof(*dhcp)) { 682e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, 683e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: packet greater than DHCP size from %s", 684e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(from)); 685e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 686e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 687e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!dhcp) 688e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp = xzalloc(sizeof(*dhcp)); 689e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(dhcp, pp, bytes); 690e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->cookie != htonl(MAGIC_COOKIE)) { 691e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: bogus cookie from %s", 692e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(from)); 693e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 694e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 695e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure it's the right transaction */ 696e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->xid != dhcp->xid) { 697e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, 698e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: wrong xid 0x%x (expecting 0x%x) from %s", 699e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, dhcp->xid, iface->state->xid, 700e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt inet_ntoa(from)); 701e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 702e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 703e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure packet is for us */ 704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->hwlen <= sizeof(dhcp->chaddr) && 705e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcmp(dhcp->chaddr, iface->hwaddr, iface->hwlen)) 706e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 707e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: xid 0x%x is not for hwaddr %s", 708e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, dhcp->xid, 709e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hwaddr_ntoa(dhcp->chaddr, sizeof(dhcp->chaddr))); 710e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 711e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 712e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_dhcp(iface, &dhcp, &from); 713e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->raw_fd == -1) 714e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 715e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 716e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(packet); 717e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(dhcp); 718e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 719e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 720e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 721e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_release(struct interface *iface) 722e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 723e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timespec ts; 724e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 725e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->new != NULL && 726e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new->cookie == htonl(MAGIC_COOKIE)) 727e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 728e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: releasing lease of %s", 729e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(iface->state->lease.addr)); 730e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->xid = dhcp_xid(iface); 731e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message(iface, DHCP_RELEASE, NULL); 732e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Give the packet a chance to go before dropping the ip */ 733e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ts.tv_sec = RELEASE_DELAY_S; 734e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ts.tv_nsec = RELEASE_DELAY_NS; 735e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nanosleep(&ts, NULL); 736e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "RELEASE"); 737e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 738e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unlink(iface->leasefile); 739f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 740f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 741e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 742e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtsend_decline(struct interface *iface) 743f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 744e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_message(iface, DHCP_DECLINE, NULL); 745e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 746e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 747e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 748e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconfigure_interface1(struct interface *iface) 749e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 750e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_state *ifs = iface->state; 751e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = ifs->options; 752e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *duid; 753e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t len = 0, ifl; 754e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 755e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Do any platform specific configuration */ 756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if_conf(iface); 757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->flags & IFF_POINTOPOINT && !(ifo->options & DHCPCD_INFORM)) 759e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options |= DHCPCD_STATIC; 760e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->flags & IFF_NOARP || 761e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)) 762e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL); 763e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_LINK && carrier_status(iface) == -1) 764e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options &= ~DHCPCD_LINK; 765e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 766e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->metric != -1) 767e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->metric = ifo->metric; 768e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 769e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we haven't specified a ClientID and our hardware address 770e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * length is greater than DHCP_CHADDR_LEN then we enforce a ClientID 771e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * of the hardware address family and the hardware address. */ 772e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->hwlen > DHCP_CHADDR_LEN) 773e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options |= DHCPCD_CLIENTID; 774e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 775e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Firewire and InfiniBand interfaces require ClientID and 776e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * the broadcast option being set. */ 777e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (iface->family) { 778e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case ARPHRD_IEEE1394: /* FALLTHROUGH */ 779e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case ARPHRD_INFINIBAND: 780e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options |= DHCPCD_CLIENTID | DHCPCD_BROADCAST; 781e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 782e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 783e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 784e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->clientid); 785e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid = NULL; 786e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (*ifo->clientid) { 787e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid = xmalloc(ifo->clientid[0] + 1); 788e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(iface->clientid, ifo->clientid, ifo->clientid[0] + 1); 789e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (ifo->options & DHCPCD_CLIENTID) { 790e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_DUID) { 791e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt duid = xmalloc(DUID_LEN); 792e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((len = get_duid(duid, iface)) == 0) 793e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "get_duid: %m"); 794e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 795e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len > 0) { 796e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid = xmalloc(len + 6); 797e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid[0] = len + 5; 798e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid[1] = 255; /* RFC 4361 */ 799e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = strlen(iface->name); 800e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifl < 5) { 801e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(iface->clientid + 2, iface->name, ifl); 802e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifl < 4) 803e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memset(iface->clientid + 2 + ifl, 804e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 0, 4 - ifl); 805f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 806e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = htonl(if_nametoindex(iface->name)); 807e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(iface->clientid + 2, &ifl, 4); 808f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 809e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (len == 0) { 810e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = iface->hwlen + 1; 811e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid = xmalloc(len + 1); 812e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid[0] = len; 813e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->clientid[1] = iface->family; 814e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(iface->clientid + 2, iface->hwaddr, 815e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->hwlen); 816e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 817e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 818e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_CLIENTID) 819e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: using ClientID %s", iface->name, 820e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hwaddr_ntoa(iface->clientid + 1, *iface->clientid)); 821e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 822e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: using hwaddr %s", iface->name, 823e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hwaddr_ntoa(iface->hwaddr, iface->hwlen)); 824e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 825e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 826e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 827e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtselect_profile(struct interface *iface, const char *profile) 828e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 829e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 830e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int ret; 831e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 832e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ret = 0; 833e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = read_config(cffile, iface->name, iface->ssid, profile); 834e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo == NULL) { 835e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: no profile %s", iface->name, profile); 836e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ret = -1; 837e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt goto exit; 838e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 839e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (profile != NULL) { 840e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(iface->state->profile, profile, 841e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(iface->state->profile)); 842e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: selected profile %s", 843e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, profile); 844e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 845e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *iface->state->profile = '\0'; 846e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_options(iface->state->options); 847e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options = ifo; 848e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 849e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtexit: 850e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (profile) 851e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure_interface1(iface); 852e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return ret; 853e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 854e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 855e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 856e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_fallback(void *arg) 857e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 858e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface; 859e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 860e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface = (struct interface *)arg; 861e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt select_profile(iface, iface->state->options->fallback); 862e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(iface); 863e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 864e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 865e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 866e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtconfigure_interface(struct interface *iface, int argc, char **argv) 867e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 868e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt select_profile(iface, NULL); 869e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_options(iface->state->options, argc, argv); 870e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure_interface1(iface); 871e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 872e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 873e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 874e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_carrier(const char *ifname) 875e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 876e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface; 877e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int carrier; 878e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 879e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_LINK)) 880e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 881e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (iface = ifaces; iface; iface = iface->next) 882e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(iface->name, ifname) == 0) 883e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 884e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!iface || !(iface->state->options->options & DHCPCD_LINK)) 885e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 886e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt carrier = carrier_status(iface); 887e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (carrier == -1) 888e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: carrier_status: %m", ifname); 889e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (carrier == 0 || !(iface->flags & IFF_RUNNING)) { 890e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->carrier != LINK_DOWN) { 891e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->carrier = LINK_DOWN; 892e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: carrier lost", iface->name); 893e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 894e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeouts(iface, start_expire, NULL); 895e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "NOCARRIER"); 896e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 897e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (carrier == 1 && (iface->flags & IFF_RUNNING)) { 898e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->carrier != LINK_UP) { 899e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->carrier = LINK_UP; 900e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: carrier acquired", iface->name); 901e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->wireless) 902e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt getifssid(iface->name, iface->ssid); 903e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure_interface(iface, margc, margv); 904e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->interval = 0; 905e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->reason = "CARRIER"; 906e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 907e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(iface); 908f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 909f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 910e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 911e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 912e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 913e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_discover(void *arg) 914e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 915e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 916e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = iface->state->options; 917e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 918e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->state = DHS_DISCOVER; 919e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->xid = dhcp_xid(iface); 920e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 921e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->fallback) 922e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(ifo->timeout, start_fallback, iface); 923e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (ifo->options & DHCPCD_IPV4LL && 924e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !IN_LINKLOCAL(htonl(iface->addr.s_addr))) 925e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 926e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (IN_LINKLOCAL(htonl(iface->state->fail.s_addr))) 927e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(RATE_LIMIT_INTERVAL, start_ipv4ll, iface); 928e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 929e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(ifo->timeout, start_ipv4ll, iface); 930e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 931e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: broadcasting for a lease", iface->name); 932e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_discover(iface); 933e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 934f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 935e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 936e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_request(void *arg) 937e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 938e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 939e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 940e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->state = DHS_REQUEST; 941e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_request(iface); 942f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 943f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 944e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 945e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_renew(void *arg) 946f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 947e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 948e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 949e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: renewing lease of %s", 950e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(iface->state->lease.addr)); 951e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->state = DHS_RENEW; 952e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->xid = dhcp_xid(iface); 953e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_renew(iface); 954e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 955e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 956e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 957e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_rebind(void *arg) 958e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 959e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 960e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 961e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: failed to renew, attempting to rebind", 962e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 963e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->state = DHS_REBIND; 964e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(send_renew, iface); 965e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.server.s_addr = 0; 966e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_rebind(iface); 967e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 968e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 969e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 970e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_timeout(void *arg) 971e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 972e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 973e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 974e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bind_interface(iface); 975e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->interval = 0; 976e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_discover(iface); 977e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 978e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 979e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct dhcp_message * 980e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdhcp_message_new(struct in_addr *addr, struct in_addr *mask) 981e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 982e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp; 983e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *p; 984e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 985e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp = xzalloc(sizeof(*dhcp)); 986e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->yiaddr = addr->s_addr; 987e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = dhcp->options; 988e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (mask && mask->s_addr != INADDR_ANY) { 989e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = DHO_SUBNETMASK; 990e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = sizeof(mask->s_addr); 991e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, &mask->s_addr, sizeof(mask->s_addr)); 992e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p+= sizeof(mask->s_addr); 993e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 994e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = DHO_END; 995e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return dhcp; 996e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 997e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 998e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic int 999e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_3rdparty(struct interface *iface) 1000e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1001e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 1002e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr addr, net, dst; 1003e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1004e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = iface->state->options; 1005e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->req_addr.s_addr != INADDR_ANY) 1006e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1007e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1008e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_address(iface->name, &addr, &net, &dst) == 1) 1009e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_ifa(RTM_NEWADDR, iface->name, &addr, &net, &dst); 1010e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 1011e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, 1012e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: waiting for 3rd party to configure IP address", 1013e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 1014e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->reason = "3RDPARTY"; 1015e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 1016e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1017e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 1; 1018e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1019e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1020e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1021e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_static(struct interface *iface) 1022e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1023e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 1024e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1025e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (handle_3rdparty(iface)) 1026e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1027e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = iface->state->options; 1028e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = 1029e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp_message_new(&ifo->req_addr, &ifo->req_mask); 1030e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 1031e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bind_interface(iface); 1032e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1033e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1034e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1035e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_inform(struct interface *iface) 1036e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1037e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (handle_3rdparty(iface)) 1038e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1039e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1040e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_TEST) { 1041e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr = iface->state->options->req_addr.s_addr; 1042e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr = iface->state->options->req_mask.s_addr; 1043f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 1044e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options->options |= DHCPCD_STATIC; 1045e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_static(iface); 1046e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1047e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1048e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->state = DHS_INFORM; 1049e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->xid = dhcp_xid(iface); 1050e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_inform(iface); 1051e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1052e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1053e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1054e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_reboot(struct interface *iface) 1055e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1056e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = iface->state->options; 1057e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1058e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_LINK && iface->carrier == LINK_DOWN) { 1059e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: waiting for carrier", iface->name); 1060e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1061e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1062e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_STATIC) { 1063e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_static(iface); 1064e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1065e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1066e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->reboot == 0 || iface->state->offer == NULL) { 1067e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_discover(iface); 1068e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1069e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1070e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_INFORM) { 1071e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: informing address of %s", 1072e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(iface->state->lease.addr)); 1073e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (iface->state->offer->cookie == 0) { 1074e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_IPV4LL) { 1075e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->claims = 0; 1076e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_arp_announce(iface); 1077e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 1078e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_discover(iface); 1079e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1080e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1081e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: rebinding lease of %s", 1082e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, inet_ntoa(iface->state->lease.addr)); 1083e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1084e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->state = DHS_REBOOT; 1085e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->xid = dhcp_xid(iface); 1086e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.server.s_addr = 0; 1087e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 1088e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->fallback) 1089e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(ifo->reboot, start_fallback, iface); 1090e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (ifo->options & DHCPCD_LASTLEASE && 1091e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.frominfo) 1092e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(ifo->reboot, start_timeout, iface); 1093e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (!(ifo->options & DHCPCD_INFORM && 1094e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options & (DHCPCD_MASTER | DHCPCD_DAEMONISED))) 1095e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(ifo->reboot, start_expire, iface); 1096e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Don't bother ARP checking as the server could NAK us first. */ 1097e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_INFORM) 1098e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_inform(iface); 1099e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_request(iface); 1101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_interface(void *arg) 1105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 1107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo = iface->state->options; 1108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct stat st; 1109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval now; 1110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint32_t l; 1111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int nolease; 1112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_carrier(iface->name); 1114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->carrier == LINK_DOWN) { 1115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: waiting for carrier", iface->name); 1116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->start_uptime = uptime(); 1120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 1121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = NULL; 1122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->arping_index < ifo->arping_len) { 1124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_arping(iface); 1125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_STATIC) { 1128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_static(iface); 1129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_INFORM) { 1132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_inform(iface); 1133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->hwlen == 0 && ifo->clientid[0] == '\0') { 1136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, "%s: needs a clientid to configure", 1137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 1138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "FAIL"); 1139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 1140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 1141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We don't want to read the old lease if we NAK an old test */ 1144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nolease = iface->state->offer && options & DHCPCD_TEST; 1145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!nolease) 1146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = read_lease(iface); 1147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->offer) { 1148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_lease(&iface->state->lease, iface->state->offer); 1149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.frominfo = 1; 1150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->offer->cookie == 0) { 1151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->offer->yiaddr == 1152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr) 1153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 1155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = NULL; 1156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (iface->state->lease.leasetime != ~0U && 1158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt stat(iface->leasefile, &st) == 0) 1159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Offset lease times and check expiry */ 1161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt gettimeofday(&now, NULL); 1162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((time_t)iface->state->lease.leasetime < 11630545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt (time_t)(now.tv_sec - st.st_mtime)) 1164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, 1166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: discarding expired lease", 1167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 1168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 1169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = NULL; 1170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.addr.s_addr = 0; 1171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = now.tv_sec - st.st_mtime; 1173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.leasetime -= l; 1174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.renewaltime -= l; 1175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.rebindtime -= l; 1176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1178f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->offer == NULL) 1180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_discover(iface); 1181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (iface->state->offer->cookie == 0 && 1182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options->options & DHCPCD_IPV4LL) 1183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_ipv4ll(iface); 1184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_reboot(iface); 1186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtinit_state(struct interface *iface, int argc, char **argv) 1190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_state *ifs; 1192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state) 1194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs = iface->state; 1195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs = iface->state = xzalloc(sizeof(*ifs)); 1197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs->state = DHS_INIT; 1199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs->reason = "PREINIT"; 1200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs->nakoff = 1; 1201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure_interface(iface, argc, argv); 1202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_TEST)) 1203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 1204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We need to drop the leasefile so that start_interface 1205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * doesn't load it. */ 1206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifs->options->options & DHCPCD_REQUEST) 1207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unlink(iface->leasefile); 1208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifs->options->options & DHCPCD_LINK) { 1210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (carrier_status(iface)) { 1211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 0: 1212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->carrier = LINK_DOWN; 1213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs->reason = "NOCARRIER"; 1214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 1: 1216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->carrier = LINK_UP; 1217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs->reason = "CARRIER"; 1218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt default: 1220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->carrier = LINK_UNKNOWN; 1221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_TEST)) 1224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 1225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 1226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->carrier = LINK_UNKNOWN; 1227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_interface(int action, const char *ifname) 1231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifs, *ifp, *ifn, *ifl = NULL; 1233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char * const argv[] = { ifname }; 1234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int i; 1235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (action == -1) { 1237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp = find_interface(ifname); 1238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp != NULL) 1239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt stop_interface(ifp); 1240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (action == 0) { 1242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_carrier(ifname); 1243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If running off an interface list, check it's in it. */ 1247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifc) { 1248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifc; i++) 1249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifv[i], ifname) == 0) 1250f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i >= ifc) 1252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs = discover_interfaces(-1, UNCONST(argv)); 1256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifs; ifp; ifp = ifp->next) { 1257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifp->name, ifname) != 0) 1258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 1259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Check if we already have the interface */ 1260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifn = ifaces; ifn; ifn = ifn->next) { 1261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifn->name, ifp->name) == 0) 1262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifn; 1264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifn) { 1266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* The flags and hwaddr could have changed */ 1267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifn->flags = ifp->flags; 1268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifn->hwlen = ifp->hwlen; 1269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->hwlen != 0) 1270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(ifn->hwaddr, ifp->hwaddr, ifn->hwlen); 1271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifl) 1273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl->next = ifp; 1274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifaces = ifp; 1276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt init_state(ifp, 0, NULL); 1278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(ifp); 1279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1280f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef RTM_CHGADDR 1283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_hwaddr(const char *ifname, unsigned char *hwaddr, size_t hwlen) 1285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp; 1287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 1288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifp->name, ifname) == 0 && ifp->hwlen <= hwlen) { 1291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = ifp->state->options; 1292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & 1293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (DHCPCD_INFORM | DHCPCD_STATIC | DHCPCD_CLIENTID)) 1294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt && ifp->state->new != NULL && 1295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->new->cookie == htonl(MAGIC_COOKIE)) 1296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, 1298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: expiring for new hardware address", 1299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->name); 1300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(ifp, "EXPIRE"); 1301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(ifp->hwaddr, hwaddr, hwlen); 1303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->hwlen = hwlen; 1304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(ifo->options & 1305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (DHCPCD_INFORM | DHCPCD_STATIC | DHCPCD_CLIENTID))) 1306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: using hwaddr %s", 1308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->name, 1309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hwaddr_ntoa(ifp->hwaddr, ifp->hwlen)); 1310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->interval = 0; 1311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->nakoff = 1; 1312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(ifp); 1313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(hwaddr); 1316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 1318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_ifa(int type, const char *ifname, 1321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct in_addr *addr, struct in_addr *net, struct in_addr *dst) 1322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp; 1324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 1325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int i; 1326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (addr->s_addr == INADDR_ANY) 1328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifp->name, ifname) == 0) 1331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp == NULL) 1333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = ifp->state->options; 1335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)) == 0 || 1336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->req_addr.s_addr != INADDR_ANY) 1337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (type) { 1340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_DELADDR: 1341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->state->new && 1342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->new->yiaddr == addr->s_addr) 1343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(ifp, "EXPIRE"); 1344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case RTM_NEWADDR: 1346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifp->state->old); 1347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->old = ifp->state->new; 1348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->new = dhcp_message_new(addr, net); 1349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->dst.s_addr = dst ? dst->s_addr : INADDR_ANY; 1350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dst) { 1351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 1; i < 255; i++) 1352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i != DHO_ROUTER && 1353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt has_option_mask(ifo->dstmask, i)) 1354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp_message_add_addr( 1355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->new, 1356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt i, *dst); 1357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->reason = "STATIC"; 1359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt build_routes(); 1360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(ifp); 1361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_INFORM) { 1362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->state = DHS_INFORM; 1363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->xid = dhcp_xid(ifp); 1364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->lease.server.s_addr = 1365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dst ? dst->s_addr : INADDR_ANY; 1366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->addr = *addr; 1367e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->net = *net; 1368e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_inform(ifp); 1369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1374e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */ 1375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1376e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_link(_unused void *arg) 1377e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1378e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (manage_link(linkfd) == -1) 1379e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "manage_link: %m"); 1380e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1381e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1382e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtif_reboot(struct interface *iface, int argc, char **argv) 1384e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1385e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct if_options *ifo; 1386e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int opt; 1387e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1388e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = iface->state->options; 1389e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = ifo->options; 1390e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure_interface(iface, argc, argv); 1391e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = iface->state->options; 1392e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->interval = 0; 1393e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) && 1394e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr != ifo->req_addr.s_addr) || 1395e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (opt & (DHCPCD_INFORM | DHCPCD_STATIC) && 1396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))) 1397e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "EXPIRE"); 1399e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1400e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 1401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = NULL; 1402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1403e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(iface); 1404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1405e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1406e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1407e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtreconf_reboot(int action, int argc, char **argv, int oi) 1408e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifl, *ifn, *ifp, *ifs, *ift; 1410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifs = discover_interfaces(argc - oi, argv + oi); 1412e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifs == NULL) 1413e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1415e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Remove any old interfaces */ 1416e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifaces) { 1417e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifl = NULL; ifl != ifaces;) { 1418e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Work our way backwards */ 1419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->next == ifl) { 1421e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifp; 1422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifn = ifs; ifn; ifn = ifn->next) 1425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifn->name, ifp->name) == 0) 1426e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifn == NULL) { 1428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifp->next; 1429e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt stop_interface(ifp); 1430f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1431f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1432e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1433e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifs; ifp && (ift = ifp->next, 1); ifp = ift) { 1435e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = NULL; 1436e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifn = ifaces; ifn; ifn = ifn->next) { 1437e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifn->name, ifp->name) == 0) 1438e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifn; 1440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1441e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifn) { 1442e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (action) 1443e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if_reboot(ifn, argc, argv); 1444e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (ifn->state->new) 1445e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure(ifn); 1446e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_interface(ifp); 1447f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 1448e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->next = NULL; 1449e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt init_state(ifp, argc, argv); 1450e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_interface(ifp); 1451e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifl) 1452e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl->next = ifp; 1453e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1454e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifaces = ifp; 1455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1458e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sort_interfaces(); 1459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1461e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* ARGSUSED */ 1462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 1463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_signal(_unused void *arg) 1464f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp, *ifl; 1466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct if_options *ifo; 1467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int sig = signal_read(); 1468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int do_release, do_rebind, i; 1469e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt do_rebind = do_release = 0; 1471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt switch (sig) { 1472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case SIGINT: 1473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "received SIGINT, stopping"); 1474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case SIGTERM: 1476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "received SIGTERM, stopping"); 1477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case SIGALRM: 14790c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff#ifdef ANDROID 14800c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff syslog(LOG_INFO, "received SIGALRM, renewing"); 14810c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff for (ifp = ifaces; ifp; ifp = ifp->next) { 14820c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff start_renew(ifp); 14830c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff } 14840c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff#else 1485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "received SIGALRM, rebinding"); 1486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifac; i++) 1487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifav[i]); 1488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifav); 1489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifav = NULL; 1490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifac = 0; 1491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifdc; i++) 1492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifdv[i]); 1493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(ifdv); 1494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifdc = 0; 1495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifdv = NULL; 1496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo = read_config(cffile, NULL, NULL, NULL); 1497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_options(ifo, margc, margv); 1498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We need to preserve these two options. */ 1499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_MASTER) 1500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options |= DHCPCD_MASTER; 1501e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_DAEMONISED) 1502e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->options |= DHCPCD_DAEMONISED; 1503e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options = ifo->options; 1504e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_options(ifo); 1505e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt reconf_reboot(1, 0, NULL, 0); 15060c4a89bb5e3205e47085b93ffec210778e474508Irfan Sheriff#endif 1507e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case SIGHUP: 1509e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "received SIGHUP, releasing"); 1510e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt do_release = 1; 1511e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1512e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case SIGUSR1: 1513e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "received SIGUSR, reconfiguring"); 1514e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1515e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->state->new) 1516e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt configure(ifp); 1517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1518e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case SIGPIPE: 1519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, "received SIGPIPE"); 1520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1521e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt default: 1522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, 1523e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "received signal %d, but don't know what to do with it", 1524e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sig); 1525e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 1526e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1527f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1528e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_TEST) 1529e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1530f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* As drop_config could re-arrange the order, we do it like this. */ 1532e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (;;) { 1533e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Be sane and drop the last config first */ 1534e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = NULL; 1535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) { 1536e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->next == NULL) 1537e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1538e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifl = ifp; 1539f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1540e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp == NULL) 1541e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1542e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->carrier != LINK_DOWN && 1543e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (do_release || 1544e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->options->options & DHCPCD_RELEASE)) 1545e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_release(ifp); 1546e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt stop_interface(ifp); 1547f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1548e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1549f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1550f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1551f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 1552e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_args(struct fd_list *fd, int argc, char **argv) 1553f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1554e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *ifp; 1555e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int do_exit = 0, do_release = 0, do_reboot = 0, do_reconf = 0; 1556e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int opt, oi = 0; 1557e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t len; 1558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t l; 1559e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct iovec iov[2]; 1560e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *tmp, *p; 1561e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1562e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd != NULL) { 1563e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Special commands for our control socket */ 1564e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(*argv, "--version") == 0) { 1565e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = strlen(VERSION) + 1; 1566e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_base = &len; 1567e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_len = sizeof(ssize_t); 1568e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_base = UNCONST(VERSION); 1569e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_len = len; 1570e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (writev(fd->fd, iov, 2) == -1) { 1571e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "writev: %m"); 1572e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1573e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1574e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1575e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (strcmp(*argv, "--getconfigfile") == 0) { 1576e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = strlen(cffile ? cffile : CONFIG) + 1; 1577e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_base = &len; 1578e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[0].iov_len = sizeof(ssize_t); 1579e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_base = cffile ? cffile : UNCONST(CONFIG); 1580e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iov[1].iov_len = len; 1581e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (writev(fd->fd, iov, 2) == -1) { 1582e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "writev: %m"); 1583e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1584e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1585e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (strcmp(*argv, "--getinterfaces") == 0) { 1587e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = 0; 1588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (argc == 1) { 1589e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len++; 1591e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = write(fd->fd, &len, sizeof(len)); 1592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len != sizeof(len)) 1593e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1594e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1595e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_interface(fd->fd, ifp); 1596e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1597e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1598e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = 0; 1599e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (argv[++opt] != NULL) { 1600e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1601e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(argv[opt], ifp->name) == 0) 1602e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len++; 1603e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1604e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = write(fd->fd, &len, sizeof(len)); 1605e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len != sizeof(len)) 1606e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1607e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = 0; 1608e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (argv[++opt] != NULL) { 1609e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1610e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(argv[opt], ifp->name) == 0) 1611e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_interface(fd->fd, ifp); 1612e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1613e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1614e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (strcmp(*argv, "--listen") == 0) { 1615e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fd->listener = 1; 1616e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1617e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1618f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1619f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1620e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Log the command */ 1621e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = 0; 1622e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (opt = 0; opt < argc; opt++) 1623e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len += strlen(argv[opt]) + 1; 1624e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tmp = p = xmalloc(len + 1); 1625e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (opt = 0; opt < argc; opt++) { 1626e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt l = strlen(argv[opt]); 1627e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(p, argv[opt], l + 1); 1628e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += l; 1629e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = ' '; 1630e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1631e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *--p = '\0'; 1632e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "control command: %s", tmp); 1633e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(tmp); 1634f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1635e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt optind = 0; 1636e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1) 1637f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 1638f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (opt) { 1639e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'g': 1640e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt do_reconf = 1; 1641e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1642e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'k': 1643e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt do_release = 1; 1644e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1645e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'n': 1646e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt do_reboot = 1; 1647e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1648e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'x': 1649e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt do_exit = 1; 1650f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1651f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1652f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1653f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1654e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We need at least one interface */ 1655e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (optind == argc) { 1656e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "handle_args: no interface"); 1657e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1658f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1659f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1660e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (do_release || do_exit) { 1661e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (oi = optind; oi < argc; oi++) { 1662e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (ifp = ifaces; ifp; ifp = ifp->next) 1663e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(ifp->name, argv[oi]) == 0) 1664f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1665e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!ifp) 1666f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1667e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (do_release) 1668e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->state->options->options |= DHCPCD_RELEASE; 1669e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifp->state->options->options & DHCPCD_RELEASE && 1670e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifp->carrier != LINK_DOWN) 1671e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_release(ifp); 1672e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt stop_interface(ifp); 1673f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1674e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1675e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1676e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1677e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt reconf_reboot(do_reboot, argc, argv, optind); 1678e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1679e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1680e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1681e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1682e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtopen_sockets(struct interface *iface) 1683e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1684e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->raw_fd == -1) { 1685e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (open_socket(iface, ETHERTYPE_IP) == -1) 1686e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: open_socket: %m", iface->name); 1687e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1688e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_event(iface->raw_fd, handle_dhcp_packet, iface); 1689e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1690e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->udp_fd == -1 && 1691e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->addr.s_addr != 0 && 1692e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new != NULL && 1693e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (iface->state->new->cookie == htonl(MAGIC_COOKIE) || 1694e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options->options & DHCPCD_INFORM)) 1695e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 1696e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (open_udp_socket(iface) == -1 && errno != EADDRINUSE) 1697e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: open_udp_socket: %m", iface->name); 1698e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1699e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1700e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1701e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1702e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtclose_sockets(struct interface *iface) 1703e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1704e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->arp_fd != -1) { 1705e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_event(iface->arp_fd); 1706e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(iface->arp_fd); 1707e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->arp_fd = -1; 1708e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1709e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->raw_fd != -1) { 1710e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_event(iface->raw_fd); 1711e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(iface->raw_fd); 1712e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->raw_fd = -1; 1713e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1714e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->udp_fd != -1) { 1715e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* we don't listen to events on the udp */ 1716e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(iface->udp_fd); 1717e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->udp_fd = -1; 1718e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1719e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1720e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 17210545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 17220545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidtvoid switchUser(void) 17230545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt{ 17240545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt gid_t groups[] = { AID_INET, AID_SHELL }; 17250545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt struct __user_cap_header_struct header; 17260545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt struct __user_cap_data_struct cap; 17270545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt 17280545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt setgroups(sizeof(groups)/sizeof(groups[0]), groups); 17290545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt 17300545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 17310545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt 17320545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt setgid(AID_DHCP); 17330545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt setuid(AID_DHCP); 17340545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt header.version = _LINUX_CAPABILITY_VERSION; 17350545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt header.pid = 0; 17360545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt cap.effective = cap.permitted = 17370545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | 17380545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt (1 << CAP_NET_BROADCAST) | (1 << CAP_NET_BIND_SERVICE); 17390545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt cap.inheritable = 0; 17400545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt capset(&header, &cap); 17410545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt} 17420545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif /* ANDROID */ 17430545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt 1744e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 1745e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmain(int argc, char **argv) 1746e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1747e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface; 1748e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int opt, oi = 0, signal_fd, sig = 0, i, control_fd; 1749e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t len; 1750e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pid_t pid; 1751e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timespec ts; 1752e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 17530545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 17540545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt switchUser(); 17550545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 1756e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt closefrom(3); 1757e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt openlog(PACKAGE, LOG_PERROR | LOG_PID, LOG_DAEMON); 1758e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt setlogmask(LOG_UPTO(LOG_INFO)); 1759e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1760e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Test for --help and --version */ 1761e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (argc > 1) { 1762e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(argv[1], "--help") == 0) { 1763f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project usage(); 1764e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1765e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (strcmp(argv[1], "--version") == 0) { 1766e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt printf(""PACKAGE" "VERSION"\n%s\n", copyright); 1767e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1768f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1769f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1770f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1771e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt i = 0; 1772e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1) 1773f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 1774f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (opt) { 1775f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 'f': 1776e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt cffile = optarg; 1777e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1778e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'g': 1779e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sig = SIGUSR1; 1780f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1781f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 'k': 1782f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sig = SIGHUP; 1783f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1784f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 'n': 1785f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sig = SIGALRM; 1786f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1787f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 'x': 1788f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sig = SIGTERM; 1789f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1790f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 'T': 1791e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt i = 1; 1792f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1793e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'U': 1794e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt i = 2; 1795f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 17960d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync case 'a': 17970d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync avoid_routes = 1; 17980d3a47d979ac35a49b2a2da9e80e16bd37aab877repo sync break; 1799e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case 'V': 1800e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt print_options(); 1801e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1802e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '?': 1803e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt usage(); 1804e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1805f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1806f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1807f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1808e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt margv = argv; 1809e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt margc = argc; 1810e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if_options = read_config(cffile, NULL, NULL, NULL); 1811e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = add_options(if_options, argc, argv); 1812e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (opt != 1) { 1813e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (opt == 0) 1814e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt usage(); 1815e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1816e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1817e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options = if_options->options; 1818e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i != 0) { 1819e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i == 1) 1820e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_TEST; 1821e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1822e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_DUMPLEASE; 1823e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_PERSISTENT; 1824e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options &= ~DHCPCD_DAEMONISE; 1825e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1826e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1827f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef THERE_IS_NO_FORK 1828e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options &= ~DHCPCD_DAEMONISE; 1829f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 1830f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1831e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_DEBUG) 1832e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt setlogmask(LOG_UPTO(LOG_DEBUG)); 1833e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_QUIET) 1834e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close(STDERR_FILENO); 1835e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1836e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & (DHCPCD_TEST | DHCPCD_DUMPLEASE))) { 1837e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we have any other args, we should run as a single dhcpcd 1838e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * instance for that interface. */ 1839e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = strlen(PIDFILE) + IF_NAMESIZE + 2; 1840e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pidfile = xmalloc(len); 1841e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (optind == argc - 1) 1842e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(pidfile, len, PIDFILE, "-", argv[optind]); 1843e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 1844e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(pidfile, len, PIDFILE, "", ""); 1845e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_MASTER; 1846f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1847e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1848f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1849e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (chdir("/") == -1) 1850e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "chdir `/': %m"); 1851e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt atexit(cleanup); 1852f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1853e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_DUMPLEASE) { 1854e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (optind != argc - 1) { 1855e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "dumplease requires an interface"); 1856e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1857f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1858e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifaces = iface = xzalloc(sizeof(*iface)); 1859e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(iface->name, argv[optind], sizeof(iface->name)); 1860e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt snprintf(iface->leasefile, sizeof(iface->leasefile), 1861e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt LEASEFILE, iface->name); 1862e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state = xzalloc(sizeof(*iface->state)); 1863e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->options = xzalloc(sizeof(*iface->state->options)); 1864e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(iface->state->options->script, if_options->script, 1865e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(iface->state->options->script)); 1866e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new = read_lease(iface); 1867e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->new == NULL && errno == ENOENT) { 1868e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt strlcpy(iface->leasefile, argv[optind], 1869e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sizeof(iface->leasefile)); 1870e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new = read_lease(iface); 1871e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1872e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->new == NULL) { 1873e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno == ENOENT) 1874e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: no lease to dump", 1875e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 1876e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1877e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1878e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->reason = "DUMP"; 1879e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt run_script(iface); 1880e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1881f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1882f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1883e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) { 1884e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt control_fd = open_control(); 1885e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (control_fd != -1) { 1886e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, 1887e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "sending commands to master dhcpcd process"); 1888e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt i = send_control(argc, argv); 1889e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i > 0) { 1890e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "send OK"); 1891e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1892e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1893e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "failed to send commands"); 1894e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1895e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1896e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1897e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno != ENOENT) 1898e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "open_control: %m"); 1899f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1900f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1901f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 19020545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifndef ANDROID 19030545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt /* android runs us as user "dhcp" */ 1904e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (geteuid()) 1905e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, 1906e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PACKAGE " will not work correctly unless run as root"); 19070545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 1908e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (sig != 0) { 19090545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 19100545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt char pidpropname[PROPERTY_KEY_MAX]; 19110545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt char pidpropval[PROPERTY_VALUE_MAX]; 19120545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt 191398564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt if (optind != argc - 1) { 191498564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt syslog(LOG_ERR, "Android requires an interface"); 191598564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt exit(EXIT_FAILURE); 191698564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt } 191798564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt 19180545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt if (snprintf(pidpropname, 19190545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt sizeof(pidpropname), 192098564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt "dhcp.%s.pid", argv[optind]) >= PROPERTY_KEY_MAX) 19210545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt exit(EXIT_FAILURE); 19220545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt property_get(pidpropname, pidpropval, NULL); 19230545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt if (strlen(pidpropval) == 0) 19240545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt exit(EXIT_FAILURE); 19250545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt pid = atoi(pidpropval); 19260545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#else 1927e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pid = read_pid(); 19280545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 1929e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (pid != 0) 1930e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "sending signal %d to pid %d", 1931e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sig, pid); 1932e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (pid == 0 || kill(pid, sig) != 0) { 1933f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (sig != SIGALRM) 1934e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, ""PACKAGE" not running"); 1935e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (pid != 0 && errno != ESRCH) { 1936e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "kill: %m"); 1937e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1938f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1939e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt unlink(pidfile); 1940e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (sig != SIGALRM) 1941e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1942e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1943e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (sig == SIGALRM) 1944e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1945f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Spin until it exits */ 1946e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "waiting for pid %d to exit", pid); 1947f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ts.tv_sec = 0; 1948f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ts.tv_nsec = 100000000; /* 10th of a second */ 1949f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for(i = 0; i < 100; i++) { 1950f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project nanosleep(&ts, NULL); 1951e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (read_pid() == 0) 1952e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 1953f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1954e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "pid %d failed to exit", pid); 1955e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1956f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1957f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1958f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1959e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_TEST)) { 19600545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 19610545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt char pidpropname[PROPERTY_KEY_MAX]; 19620545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt char pidpropval[PROPERTY_VALUE_MAX]; 19630545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 19640545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifndef ANDROID 1965e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((pid = read_pid()) > 0 && 1966f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project kill(pid, 0) == 0) 1967f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 1968e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, ""PACKAGE 1969e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt " already running on pid %d (%s)", 1970e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pid, pidfile); 1971e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1972f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1973e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1974e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure we have the needed directories */ 1975e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST) { 1976e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "mkdir `%s': %m", RUNDIR); 1977e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1978e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1979e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (mkdir(DBDIR, 0755) == -1 && errno != EEXIST) { 1980e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "mkdir `%s': %m", DBDIR); 1981e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1982f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 19830545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 1984e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt pidfd = open(pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0664); 1985e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (pidfd == -1) { 1986e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "open `%s': %m", pidfile); 1987e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1988e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1989f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Lock the file so that only one instance of dhcpcd runs 1990f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * on an interface */ 1991e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (flock(pidfd, LOCK_EX | LOCK_NB) == -1) { 1992e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "flock `%s': %m", pidfile); 1993e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 1994e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1995e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (set_cloexec(pidfd) == -1) 1996e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 19970545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 199898564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt if (optind != argc - 1) { 199998564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt syslog(LOG_ERR, "Android requires an interface"); 200098564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt exit(EXIT_FAILURE); 200198564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt } 200298564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt 20030545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt if (snprintf(pidpropname, 20040545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt sizeof(pidpropname), 200598564e9e7ad91339b5d4fe85b6ecff6e58a25751Dmitry Shmidt "dhcp.%s.pid", argv[optind]) >= PROPERTY_KEY_MAX) 20060545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt exit(EXIT_FAILURE); 20070545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt if (snprintf(pidpropval, sizeof(pidpropval), "%d", getpid()) >= PROPERTY_VALUE_MAX) 20080545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt exit(EXIT_FAILURE); 20090545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt property_set(pidpropname, pidpropval); 20100545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#else 2011e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt writepid(pidfd, getpid()); 20120545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 2013e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2014e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2015e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "version " VERSION " starting"); 2016e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2017e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((signal_fd = signal_init()) == -1) 2018e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 2019e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (signal_setup() == -1) 2020e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 2021e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_event(signal_fd, handle_signal, NULL); 2022e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2023e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_MASTER) { 2024e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (start_control() == -1) { 2025e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "start_control: %m"); 2026e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 2027f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 2028e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2029f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 2030e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (init_sockets() == -1) { 2031e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "init_socket: %m"); 2032e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 2033e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2034e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (if_options->options & DHCPCD_LINK) { 2035e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt linkfd = open_link_socket(); 2036e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (linkfd == -1) 2037e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "open_link_socket: %m"); 2038e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 2039e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_event(linkfd, handle_link, NULL); 2040f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 2041f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 2042e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifc = argc - optind; 2043e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifv = argv + optind; 2044e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2045e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* When running dhcpcd against a single interface, we need to retain 2046e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * the old behaviour of waiting for an IP address */ 2047e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifc == 1) 2048e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_WAITIP; 2049e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2050e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifaces = discover_interfaces(ifc, ifv); 2051e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < ifc; i++) { 2052e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (iface = ifaces; iface; iface = iface->next) 2053e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (strcmp(iface->name, ifv[i]) == 0) 2054e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 2055e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!iface) 2056e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: interface not found or invalid", 2057e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifv[i]); 2058e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2059e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!ifaces) { 2060e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifc == 0) 2061e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "no valid interfaces found"); 2062e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 2063e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 2064e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_LINK)) { 2065e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, 2066e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "aborting as link detection is disabled"); 2067e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 2068e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2069f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 2070f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 2071e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_BACKGROUND) 2072e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt daemonise(); 2073f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 2074e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = 0; 2075e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (iface = ifaces; iface; iface = iface->next) { 2076e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt init_state(iface, argc, argv); 2077e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->carrier != LINK_DOWN) 2078e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = 1; 2079f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 2080e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2081e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(options & DHCPCD_BACKGROUND)) { 2082e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* If we don't have a carrier, we may have to wait for a second 2083e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * before one becomes available if we brought an interface up. */ 2084e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (opt == 0 && 2085e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options & DHCPCD_LINK && 2086e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options & DHCPCD_WAITUP && 2087e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(options & DHCPCD_WAITIP)) 2088e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 2089e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ts.tv_sec = 1; 2090e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ts.tv_nsec = 0; 2091e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nanosleep(&ts, NULL); 2092e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (iface = ifaces; iface; iface = iface->next) { 2093e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_carrier(iface->name); 2094e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->carrier != LINK_DOWN) { 2095e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt = 1; 2096e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 2097e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2098e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2099e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (opt == 0 && 2101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options & DHCPCD_LINK && 2102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt !(options & DHCPCD_WAITIP)) 2103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 2104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_WARNING, "no interfaces have a carrier"); 2105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt daemonise(); 2106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (if_options->timeout > 0) { 2107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (options & DHCPCD_IPV4LL) 2108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt options |= DHCPCD_TIMEOUT_IPV4LL; 2109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(if_options->timeout, 2110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt handle_exit_timeout, NULL); 2111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 2112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 2113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_options(if_options); 2114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if_options = NULL; 2115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sort_interfaces(); 2117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (iface = ifaces; iface; iface = iface->next) 2118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(0, start_interface, iface); 2119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 2120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_eloop(); 2121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_SUCCESS); 2122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 2123