158f0484fSRodney W. Grimes /*-
2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro F. Giffuni *
458f0484fSRodney W. Grimes * Copyright (c) 1990, 1993
558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved.
658f0484fSRodney W. Grimes *
758f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without
858f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions
958f0484fSRodney W. Grimes * are met:
1058f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
1158f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer.
1258f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
1358f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
1458f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
1658f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software
1758f0484fSRodney W. Grimes * without specific prior written permission.
1858f0484fSRodney W. Grimes *
1958f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2058f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2158f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2258f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2358f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2458f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2558f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2658f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2758f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2858f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2958f0484fSRodney W. Grimes * SUCH DAMAGE.
3058f0484fSRodney W. Grimes */
3158f0484fSRodney W. Grimes
3258f0484fSRodney W. Grimes #include <sys/types.h>
3358f0484fSRodney W. Grimes #include <sys/socket.h>
3474e540d7SGleb Smirnoff #include <net/if.h>
3558f0484fSRodney W. Grimes #include <net/if_dl.h>
3658f0484fSRodney W. Grimes #include <string.h>
3758f0484fSRodney W. Grimes
3858f0484fSRodney W. Grimes /* States*/
3958f0484fSRodney W. Grimes #define NAMING 0
4058f0484fSRodney W. Grimes #define GOTONE 1
4158f0484fSRodney W. Grimes #define GOTTWO 2
4258f0484fSRodney W. Grimes #define RESET 3
4358f0484fSRodney W. Grimes /* Inputs */
4458f0484fSRodney W. Grimes #define DIGIT (4*0)
4558f0484fSRodney W. Grimes #define END (4*1)
4658f0484fSRodney W. Grimes #define DELIM (4*2)
4758f0484fSRodney W. Grimes #define LETTER (4*3)
4858f0484fSRodney W. Grimes
4958f0484fSRodney W. Grimes void
link_addr(const char * addr,struct sockaddr_dl * sdl)50626c9d74SCraig Rodrigues link_addr(const char *addr, struct sockaddr_dl *sdl)
5158f0484fSRodney W. Grimes {
528fb3f3f6SDavid E. O'Brien char *cp = sdl->sdl_data;
5358f0484fSRodney W. Grimes char *cplim = sdl->sdl_len + (char *)sdl;
548fb3f3f6SDavid E. O'Brien int byte = 0, state = NAMING, new;
5558f0484fSRodney W. Grimes
5658f0484fSRodney W. Grimes bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
5758f0484fSRodney W. Grimes sdl->sdl_family = AF_LINK;
5858f0484fSRodney W. Grimes do {
5958f0484fSRodney W. Grimes state &= ~LETTER;
6058f0484fSRodney W. Grimes if ((*addr >= '0') && (*addr <= '9')) {
6158f0484fSRodney W. Grimes new = *addr - '0';
6258f0484fSRodney W. Grimes } else if ((*addr >= 'a') && (*addr <= 'f')) {
6358f0484fSRodney W. Grimes new = *addr - 'a' + 10;
6458f0484fSRodney W. Grimes } else if ((*addr >= 'A') && (*addr <= 'F')) {
6558f0484fSRodney W. Grimes new = *addr - 'A' + 10;
6658f0484fSRodney W. Grimes } else if (*addr == 0) {
6758f0484fSRodney W. Grimes state |= END;
6858f0484fSRodney W. Grimes } else if (state == NAMING &&
6958f0484fSRodney W. Grimes (((*addr >= 'A') && (*addr <= 'Z')) ||
7058f0484fSRodney W. Grimes ((*addr >= 'a') && (*addr <= 'z'))))
7158f0484fSRodney W. Grimes state |= LETTER;
7258f0484fSRodney W. Grimes else
7358f0484fSRodney W. Grimes state |= DELIM;
7458f0484fSRodney W. Grimes addr++;
7558f0484fSRodney W. Grimes switch (state /* | INPUT */) {
7658f0484fSRodney W. Grimes case NAMING | DIGIT:
7758f0484fSRodney W. Grimes case NAMING | LETTER:
7858f0484fSRodney W. Grimes *cp++ = addr[-1];
7958f0484fSRodney W. Grimes continue;
8058f0484fSRodney W. Grimes case NAMING | DELIM:
8158f0484fSRodney W. Grimes state = RESET;
8258f0484fSRodney W. Grimes sdl->sdl_nlen = cp - sdl->sdl_data;
8358f0484fSRodney W. Grimes continue;
8458f0484fSRodney W. Grimes case GOTTWO | DIGIT:
8558f0484fSRodney W. Grimes *cp++ = byte;
8658f0484fSRodney W. Grimes /* FALLTHROUGH */
8758f0484fSRodney W. Grimes case RESET | DIGIT:
8858f0484fSRodney W. Grimes state = GOTONE;
8958f0484fSRodney W. Grimes byte = new;
9058f0484fSRodney W. Grimes continue;
9158f0484fSRodney W. Grimes case GOTONE | DIGIT:
9258f0484fSRodney W. Grimes state = GOTTWO;
9358f0484fSRodney W. Grimes byte = new + (byte << 4);
9458f0484fSRodney W. Grimes continue;
9558f0484fSRodney W. Grimes default: /* | DELIM */
9658f0484fSRodney W. Grimes state = RESET;
9758f0484fSRodney W. Grimes *cp++ = byte;
9858f0484fSRodney W. Grimes byte = 0;
9958f0484fSRodney W. Grimes continue;
10058f0484fSRodney W. Grimes case GOTONE | END:
10158f0484fSRodney W. Grimes case GOTTWO | END:
10258f0484fSRodney W. Grimes *cp++ = byte;
10358f0484fSRodney W. Grimes /* FALLTHROUGH */
10458f0484fSRodney W. Grimes case RESET | END:
10558f0484fSRodney W. Grimes break;
10658f0484fSRodney W. Grimes }
10758f0484fSRodney W. Grimes break;
10858f0484fSRodney W. Grimes } while (cp < cplim);
10958f0484fSRodney W. Grimes sdl->sdl_alen = cp - LLADDR(sdl);
11058f0484fSRodney W. Grimes new = cp - (char *)sdl;
11158f0484fSRodney W. Grimes if (new > sizeof(*sdl))
11258f0484fSRodney W. Grimes sdl->sdl_len = new;
11358f0484fSRodney W. Grimes return;
11458f0484fSRodney W. Grimes }
11558f0484fSRodney W. Grimes
116905dd80fSPedro F. Giffuni static const char hexlist[] = "0123456789abcdef";
11758f0484fSRodney W. Grimes
11858f0484fSRodney W. Grimes char *
link_ntoa(const struct sockaddr_dl * sdl)119626c9d74SCraig Rodrigues link_ntoa(const struct sockaddr_dl *sdl)
12058f0484fSRodney W. Grimes {
12158f0484fSRodney W. Grimes static char obuf[64];
12274e540d7SGleb Smirnoff _Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small");
12374e540d7SGleb Smirnoff char *out;
124faf19a69SGleb Smirnoff const u_char *in, *inlim;
12574e540d7SGleb Smirnoff int namelen, i, rem;
12658f0484fSRodney W. Grimes
12774e540d7SGleb Smirnoff namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ;
12874e540d7SGleb Smirnoff
12974e540d7SGleb Smirnoff out = obuf;
13074e540d7SGleb Smirnoff rem = sizeof(obuf);
13174e540d7SGleb Smirnoff if (namelen > 0) {
13274e540d7SGleb Smirnoff bcopy(sdl->sdl_data, out, namelen);
13374e540d7SGleb Smirnoff out += namelen;
13474e540d7SGleb Smirnoff rem -= namelen;
13574e540d7SGleb Smirnoff if (sdl->sdl_alen > 0) {
13658f0484fSRodney W. Grimes *out++ = ':';
13774e540d7SGleb Smirnoff rem--;
13858f0484fSRodney W. Grimes }
13974e540d7SGleb Smirnoff }
14074e540d7SGleb Smirnoff
141faf19a69SGleb Smirnoff in = (const u_char *)sdl->sdl_data + sdl->sdl_nlen;
14274e540d7SGleb Smirnoff inlim = in + sdl->sdl_alen;
14374e540d7SGleb Smirnoff
14474e540d7SGleb Smirnoff while (in < inlim && rem > 1) {
145faf19a69SGleb Smirnoff if (in != (const u_char *)sdl->sdl_data + sdl->sdl_nlen) {
14658f0484fSRodney W. Grimes *out++ = '.';
14774e540d7SGleb Smirnoff rem--;
14874e540d7SGleb Smirnoff }
14958f0484fSRodney W. Grimes i = *in++;
15058f0484fSRodney W. Grimes if (i > 0xf) {
15174e540d7SGleb Smirnoff if (rem < 3)
15274e540d7SGleb Smirnoff break;
153faf19a69SGleb Smirnoff *out++ = hexlist[i >> 4];
15474e540d7SGleb Smirnoff *out++ = hexlist[i & 0xf];
15574e540d7SGleb Smirnoff rem -= 2;
15674e540d7SGleb Smirnoff } else {
15774e540d7SGleb Smirnoff if (rem < 2)
15874e540d7SGleb Smirnoff break;
15974e540d7SGleb Smirnoff *out++ = hexlist[i];
160faf19a69SGleb Smirnoff rem--;
16174e540d7SGleb Smirnoff }
16258f0484fSRodney W. Grimes }
16358f0484fSRodney W. Grimes *out = 0;
16458f0484fSRodney W. Grimes return (obuf);
16558f0484fSRodney W. Grimes }
166