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