/*1* Copyright 2004 The Aerospace Corporation. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions, and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions, and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. The name of The Aerospace Corporation may not be used to endorse or13* promote products derived from this software.14*15* THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*27* Copyright (c) 199528* Bill Paul <[email protected]>. All rights reserved.29*30* Redistribution and use in source and binary forms, with or without31* modification, are permitted provided that the following conditions32* are met:33* 1. Redistributions of source code must retain the above copyright34* notice, this list of conditions and the following disclaimer.35* 2. Redistributions in binary form must reproduce the above copyright36* notice, this list of conditions and the following disclaimer in the37* documentation and/or other materials provided with the distribution.38* 3. All advertising materials mentioning features or use of this software39* must display the following acknowledgement:40* This product includes software developed by Bill Paul.41* 4. Neither the name of the author nor the names of any co-contributors42* may be used to endorse or promote products derived from this software43* without specific prior written permission.44*45* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND46* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE47* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE48* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE49* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL50* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS51* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)52* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT53* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY54* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF55* SUCH DAMAGE.56*57* EUI-64 conversion and lookup routines58*59*60* Converted from ether_addr.c rev61* FreeBSD: src/lib/libc/net/eui64.c,v 1.15 2002/04/08 07:51:10 ru Exp62* by Brooks Davis63*64* Written by Bill Paul <[email protected]>65* Center for Telecommunications Research66* Columbia University, New York City67*/6869#include <stdio.h>70#include <paths.h>71#include <sys/param.h>72#include <sys/eui64.h>73#include <string.h>74#include <stdlib.h>75#ifdef YP76#include <rpc/rpc.h>77#include <rpcsvc/yp_prot.h>78#include <rpcsvc/ypclnt.h>79#endif8081#ifndef _PATH_EUI6482#define _PATH_EUI64 "/etc/eui64"83#endif8485static int eui64_line(const char *l, struct eui64 *e, char *hostname,86size_t len);8788/*89* Parse a string of text containing an EUI-64 and hostname90* and separate it into its component parts.91*/92static int93eui64_line(const char *l, struct eui64 *e, char *hostname, size_t len)94{95char *line, *linehead, *cur;9697linehead = strdup(l);98if (linehead == NULL)99return (-1);100line = linehead;101102/* Find and parse the EUI64 */103while ((cur = strsep(&line, " \t\r\n")) != NULL) {104if (*cur != '\0') {105if (eui64_aton(cur, e) == 0)106break;107else108goto bad;109}110}111112/* Find the hostname */113while ((cur = strsep(&line, " \t\r\n")) != NULL) {114if (*cur != '\0') {115if (strlcpy(hostname, cur, len) <= len)116break;117else118goto bad;119}120}121122/* Make sure what remains is either whitespace or a comment */123while ((cur = strsep(&line, " \t\r\n")) != NULL) {124if (*cur == '#')125break;126if (*cur != '\0')127goto bad;128}129130free(linehead);131return (0);132133bad:134free(linehead);135return (-1);136}137138/*139* Convert an ASCII representation of an EUI-64 to binary form.140*/141int142eui64_aton(const char *a, struct eui64 *e)143{144int i;145unsigned int o0, o1, o2, o3, o4, o5, o6, o7;146147/* canonical form */148i = sscanf(a, "%x-%x-%x-%x-%x-%x-%x-%x",149&o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);150if (i == EUI64_LEN)151goto good;152/* ethernet form */153i = sscanf(a, "%x:%x:%x:%x:%x:%x:%x:%x",154&o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);155if (i == EUI64_LEN)156goto good;157/* classic fwcontrol/dconschat form */158i = sscanf(a, "0x%2x%2x%2x%2x%2x%2x%2x%2x",159&o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);160if (i == EUI64_LEN)161goto good;162/* MAC format (-) */163i = sscanf(a, "%x-%x-%x-%x-%x-%x",164&o0, &o1, &o2, &o5, &o6, &o7);165if (i == 6) {166o3 = 0xff;167o4 = 0xfe;168goto good;169}170/* MAC format (:) */171i = sscanf(a, "%x:%x:%x:%x:%x:%x",172&o0, &o1, &o2, &o5, &o6, &o7);173if (i == 6) {174o3 = 0xff;175o4 = 0xfe;176goto good;177}178179return (-1);180181good:182e->octet[0]=o0;183e->octet[1]=o1;184e->octet[2]=o2;185e->octet[3]=o3;186e->octet[4]=o4;187e->octet[5]=o5;188e->octet[6]=o6;189e->octet[7]=o7;190191return (0);192}193194/*195* Convert a binary representation of an EUI-64 to an ASCII string.196*/197int198eui64_ntoa(const struct eui64 *id, char *a, size_t len)199{200int i;201202i = snprintf(a, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",203id->octet[0], id->octet[1], id->octet[2], id->octet[3],204id->octet[4], id->octet[5], id->octet[6], id->octet[7]);205if (i < 23 || i >= len)206return (-1);207return (0);208}209210/*211* Map an EUI-64 to a hostname. Use either /etc/eui64 or NIS/YP.212*/213int214eui64_ntohost(char *hostname, size_t len, const struct eui64 *id)215{216FILE *fp;217char buf[BUFSIZ + 2];218struct eui64 local_eui64;219char local_host[MAXHOSTNAMELEN];220#ifdef YP221char *result;222int resultlen;223char eui64_a[24];224char *yp_domain;225#endif226if ((fp = fopen(_PATH_EUI64, "re")) == NULL)227return (1);228229while (fgets(buf,BUFSIZ,fp)) {230if (buf[0] == '#')231continue;232#ifdef YP233if (buf[0] == '+') {234if (yp_get_default_domain(&yp_domain))235continue;236eui64_ntoa(id, eui64_a, sizeof(eui64_a));237if (yp_match(yp_domain, "eui64.byid", eui64_a,238strlen(eui64_a), &result, &resultlen)) {239continue;240}241strncpy(buf, result, resultlen);242buf[resultlen] = '\0';243free(result);244}245#endif246if (eui64_line(buf, &local_eui64, local_host,247sizeof(local_host)) == 0) {248if (bcmp(&local_eui64.octet[0],249&id->octet[0], EUI64_LEN) == 0) {250/* We have a match */251strcpy(hostname, local_host);252fclose(fp);253return(0);254}255}256}257fclose(fp);258return (1);259}260261/*262* Map a hostname to an EUI-64 using /etc/eui64 or NIS/YP.263*/264int265eui64_hostton(const char *hostname, struct eui64 *id)266{267FILE *fp;268char buf[BUFSIZ + 2];269struct eui64 local_eui64;270char local_host[MAXHOSTNAMELEN];271#ifdef YP272char *result;273int resultlen;274char *yp_domain;275#endif276if ((fp = fopen(_PATH_EUI64, "re")) == NULL)277return (1);278279while (fgets(buf,BUFSIZ,fp)) {280if (buf[0] == '#')281continue;282#ifdef YP283if (buf[0] == '+') {284if (yp_get_default_domain(&yp_domain))285continue;286if (yp_match(yp_domain, "eui64.byname", hostname,287strlen(hostname), &result, &resultlen)) {288continue;289}290strncpy(buf, result, resultlen);291buf[resultlen] = '\0';292free(result);293}294#endif295if (eui64_line(buf, &local_eui64, local_host,296sizeof(local_host)) == 0) {297if (strcmp(hostname, local_host) == 0) {298/* We have a match */299bcopy(&local_eui64, id, sizeof(struct eui64));300fclose(fp);301return(0);302}303}304}305fclose(fp);306return (1);307}308309310