1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* 2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon 3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name> 4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved 5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without 7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions 8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met: 9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright 10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer. 11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright 12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer in the 13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * documentation and/or other materials provided with the distribution. 14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE. 26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DUID_TIME_EPOCH 946684800 29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DUID_LLT 1 30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DUID_LL 3 31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/socket.h> 33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/types.h> 34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if.h> 36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if_arp.h> 37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h> 39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdio.h> 40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h> 41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h> 42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <time.h> 43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h> 44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef ARPHRD_NETROM 46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan# define ARPHRD_NETROM 0 47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h" 50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcpcd.h" 51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "duid.h" 52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic size_t 54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanduid_make(unsigned char *d, const struct interface *ifp, uint16_t type) 55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned char *p; 57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint16_t u16; 58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan time_t t; 59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint32_t u32; 60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p = d; 62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u16 = htons(type); 63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(p, &u16, 2); 64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += 2; 65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u16 = htons(ifp->family); 66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(p, &u16, 2); 67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += 2; 68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type == DUID_LLT) { 69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* time returns seconds from jan 1 1970, but DUID-LLT is 70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * seconds from jan 1 2000 modulo 2^32 */ 71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t = time(NULL) - DUID_TIME_EPOCH; 72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u32 = htonl((uint32_t)t & 0xffffffff); 73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(p, &u32, 4); 74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += 4; 75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Finally, add the MAC address of the interface */ 77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(p, ifp->hwaddr, ifp->hwlen); 78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += ifp->hwlen; 79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (size_t)(p - d); 80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DUID_STRLEN DUID_LEN * 3 83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic size_t 84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanduid_get(unsigned char *d, const struct interface *ifp) 85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan FILE *fp; 87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int x = 0; 88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len = 0; 89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char line[DUID_STRLEN]; 90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct interface *ifp2; 91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If we already have a DUID then use it as it's never supposed 93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * to change once we have one even if the interfaces do */ 94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((fp = fopen(DUID, "r"))) { 95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (fgets(line, DUID_STRLEN, fp)) { 96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = strlen(line); 97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len) { 98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (line[len - 1] == '\n') 99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan line[len - 1] = '\0'; 100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = hwaddr_aton(NULL, line); 102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len && len <= DUID_LEN) { 103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hwaddr_aton(d, line); 104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = 0; 107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len) 110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return len; 111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (errno != ENOENT) 113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, 114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "error reading DUID: %s: %m", DUID); 115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* No file? OK, lets make one based on our interface */ 118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->family == ARPHRD_NETROM) { 119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_WARNING, 120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: is a NET/ROM psuedo interface", ifp->name); 121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) { 122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp2->family != ARPHRD_NETROM) 123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp2) { 126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp = ifp2; 127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_WARNING, 128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "picked interface %s to generate a DUID", 129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_WARNING, 132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "no interfaces have a fixed hardware address"); 133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return duid_make(d, ifp, DUID_LL); 134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!(fp = fopen(DUID, "w"))) { 138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, "error writing DUID: %s: %m", DUID); 139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return duid_make(d, ifp, DUID_LL); 140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = duid_make(d, ifp, DUID_LLT); 142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan x = fprintf(fp, "%s\n", hwaddr_ntoa(d, len, line, sizeof(line))); 143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fclose(fp); 144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Failed to write the duid? scrub it, we cannot use it */ 145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (x < 1) { 146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, "error writing DUID: %s: %m", DUID); 147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unlink(DUID); 148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return duid_make(d, ifp, DUID_LL); 149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return len; 151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tansize_t duid_init(const struct interface *ifp) 154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->ctx->duid == NULL) { 157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ctx->duid = malloc(DUID_LEN); 158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->ctx->duid == NULL) { 159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_ERR, "%s: %m", __func__); 160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->ctx->duid_len = duid_get(ifp->ctx->duid, ifp); 163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ifp->ctx->duid_len; 165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 166