149884Ssheldonh/*- 249884Ssheldonh * Copyright (c) 1990, 1993 349884Ssheldonh * The Regents of the University of California. All rights reserved. 449884Ssheldonh * 549884Ssheldonh * Redistribution and use in source and binary forms, with or without 649884Ssheldonh * modification, are permitted provided that the following conditions 749884Ssheldonh * are met: 849884Ssheldonh * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 1049884Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 4. Neither the name of the University nor the names of its contributors 1436152Scharnier * may be used to endorse or promote products derived from this software 1550471Speter * without specific prior written permission. 161556Srgrimes * 171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1849884Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2493345Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2576883Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2686619Sknu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271556Srgrimes * SUCH DAMAGE. 281556Srgrimes */ 291556Srgrimes 301556Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 311556Srgrimesstatic char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93"; 3286505Sknu#endif /* LIBC_SCCS and not lint */ 3386505Sknu#include <sys/cdefs.h> 3486505Sknu__FBSDID("$FreeBSD: releng/10.1/lib/libc/net/linkaddr.c 309696 2016-12-07 23:34:06Z glebius $"); 3586618Sknu 3688084Sache#include <sys/types.h> 3788084Sache#include <sys/socket.h> 3896376Salfred#include <net/if.h> 3986618Sknu#include <net/if_dl.h> 4086618Sknu#include <string.h> 4186618Sknu 4286618Sknu/* States*/ 4386618Sknu#define NAMING 0 4486618Sknu#define GOTONE 1 4586618Sknu#define GOTTWO 2 4686618Sknu#define RESET 3 4786618Sknu/* Inputs */ 4886618Sknu#define DIGIT (4*0) 4986618Sknu#define END (4*1) 5086618Sknu#define DELIM (4*2) 5149884Ssheldonh#define LETTER (4*3) 5249884Ssheldonh 5349884Ssheldonhvoid 5449884Ssheldonhlink_addr(addr, sdl) 5549884Ssheldonh const char *addr; 5649884Ssheldonh struct sockaddr_dl *sdl; 5749884Ssheldonh{ 5849884Ssheldonh char *cp = sdl->sdl_data; 5949884Ssheldonh char *cplim = sdl->sdl_len + (char *)sdl; 6049884Ssheldonh int byte = 0, state = NAMING, new; 6149884Ssheldonh 621556Srgrimes bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1); 6349884Ssheldonh sdl->sdl_family = AF_LINK; 6449884Ssheldonh do { 6549884Ssheldonh state &= ~LETTER; 6649884Ssheldonh if ((*addr >= '0') && (*addr <= '9')) { 671556Srgrimes new = *addr - '0'; 6849884Ssheldonh } else if ((*addr >= 'a') && (*addr <= 'f')) { 6949884Ssheldonh new = *addr - 'a' + 10; 7049884Ssheldonh } else if ((*addr >= 'A') && (*addr <= 'F')) { 7149884Ssheldonh new = *addr - 'A' + 10; 7249884Ssheldonh } else if (*addr == 0) { 7349884Ssheldonh state |= END; 7449884Ssheldonh } else if (state == NAMING && 7549884Ssheldonh (((*addr >= 'A') && (*addr <= 'Z')) || 7649884Ssheldonh ((*addr >= 'a') && (*addr <= 'z')))) 7749884Ssheldonh state |= LETTER; 7849884Ssheldonh else 7949884Ssheldonh state |= DELIM; 8049884Ssheldonh addr++; 8149884Ssheldonh switch (state /* | INPUT */) { 8249884Ssheldonh case NAMING | DIGIT: 8349884Ssheldonh case NAMING | LETTER: 8449884Ssheldonh *cp++ = addr[-1]; 8549884Ssheldonh continue; 8649884Ssheldonh case NAMING | DELIM: 8749884Ssheldonh state = RESET; 8849884Ssheldonh sdl->sdl_nlen = cp - sdl->sdl_data; 8949884Ssheldonh continue; 9049884Ssheldonh case GOTTWO | DIGIT: 9149884Ssheldonh *cp++ = byte; 9249884Ssheldonh /* FALLTHROUGH */ 9349884Ssheldonh case RESET | DIGIT: 9449884Ssheldonh state = GOTONE; 9549884Ssheldonh byte = new; 9649884Ssheldonh continue; 9749884Ssheldonh case GOTONE | DIGIT: 9849884Ssheldonh state = GOTTWO; 9949884Ssheldonh byte = new + (byte << 4); 10049884Ssheldonh continue; 10149884Ssheldonh default: /* | DELIM */ 10249884Ssheldonh state = RESET; 10349884Ssheldonh *cp++ = byte; 10449884Ssheldonh byte = 0; 10549884Ssheldonh continue; 10649884Ssheldonh case GOTONE | END: 10749884Ssheldonh case GOTTWO | END: 10849884Ssheldonh *cp++ = byte; 1091556Srgrimes /* FALLTHROUGH */ 1101556Srgrimes case RESET | END: 11149884Ssheldonh break; 11249884Ssheldonh } 11349884Ssheldonh break; 11449884Ssheldonh } while (cp < cplim); 11549884Ssheldonh sdl->sdl_alen = cp - LLADDR(sdl); 11649884Ssheldonh new = cp - (char *)sdl; 1171556Srgrimes if (new > sizeof(*sdl)) 1181556Srgrimes sdl->sdl_len = new; 11949884Ssheldonh return; 12049884Ssheldonh} 12149884Ssheldonh 12249884Ssheldonhstatic const char hexlist[] = "0123456789abcdef"; 12349884Ssheldonh 12449884Ssheldonhchar * 12549884Ssheldonhlink_ntoa(sdl) 12649884Ssheldonh const struct sockaddr_dl *sdl; 12749884Ssheldonh{ 12849884Ssheldonh static char obuf[64]; 12949884Ssheldonh _Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small"); 13049884Ssheldonh char *out; 13149884Ssheldonh const u_char *in, *inlim; 13249884Ssheldonh int namelen, i, rem; 13349884Ssheldonh 13449884Ssheldonh namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ; 13549884Ssheldonh 13649884Ssheldonh out = obuf; 13749884Ssheldonh rem = sizeof(obuf); 13849884Ssheldonh if (namelen > 0) { 13949884Ssheldonh bcopy(sdl->sdl_data, out, namelen); 14049884Ssheldonh out += namelen; 14149884Ssheldonh rem -= namelen; 14249884Ssheldonh if (sdl->sdl_alen > 0) { 14349884Ssheldonh *out++ = ':'; 14449884Ssheldonh rem--; 14549884Ssheldonh } 14649884Ssheldonh } 14749884Ssheldonh 14849884Ssheldonh in = (const u_char *)sdl->sdl_data + sdl->sdl_nlen; 14949884Ssheldonh inlim = in + sdl->sdl_alen; 15049884Ssheldonh 15149884Ssheldonh while (in < inlim && rem > 1) { 15249884Ssheldonh if (in != (const u_char *)sdl->sdl_data + sdl->sdl_nlen) { 15349884Ssheldonh *out++ = '.'; 15449884Ssheldonh rem--; 15549884Ssheldonh } 15649884Ssheldonh i = *in++; 15749884Ssheldonh if (i > 0xf) { 15849884Ssheldonh if (rem < 3) 15949884Ssheldonh break; 16049884Ssheldonh *out++ = hexlist[i >> 4]; 16149884Ssheldonh *out++ = hexlist[i & 0xf]; 16249884Ssheldonh rem -= 2; 1631556Srgrimes } else { 1641556Srgrimes if (rem < 2) 16549884Ssheldonh break; 16649884Ssheldonh *out++ = hexlist[i]; 1671556Srgrimes rem--; 16890111Simp } 16990111Simp } 17090111Simp *out = 0; 17190111Simp return (obuf); 17290111Simp} 17393345Sache