lib/libc/net/linkaddr.c

http://www.minix3.org/ · C · 169 lines · 124 code · 12 blank · 33 comment · 28 complexity · 40bc7f74aa668fc62b2474903ad5e9bb MD5 · raw file

  1. /* $NetBSD: linkaddr.c,v 1.14 2005/11/29 03:11:59 christos Exp $ */
  2. /*-
  3. * Copyright (c) 1990, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <sys/cdefs.h>
  31. #if defined(LIBC_SCCS) && !defined(lint)
  32. #if 0
  33. static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
  34. #else
  35. __RCSID("$NetBSD: linkaddr.c,v 1.14 2005/11/29 03:11:59 christos Exp $");
  36. #endif
  37. #endif /* LIBC_SCCS and not lint */
  38. #include <sys/types.h>
  39. #include <sys/socket.h>
  40. #include <net/if_dl.h>
  41. #include <assert.h>
  42. #include <string.h>
  43. /* States*/
  44. #define NAMING 0
  45. #define GOTONE 1
  46. #define GOTTWO 2
  47. #define RESET 3
  48. /* Inputs */
  49. #define DIGIT (4*0)
  50. #define END (4*1)
  51. #define DELIM (4*2)
  52. #define LETTER (4*3)
  53. void
  54. link_addr(addr, sdl)
  55. register const char *addr;
  56. register struct sockaddr_dl *sdl;
  57. {
  58. register char *cp = sdl->sdl_data;
  59. char *cplim = sdl->sdl_len + (char *)(void *)sdl;
  60. register int byte = 0, state = NAMING;
  61. register int newaddr = 0; /* pacify gcc */
  62. _DIAGASSERT(addr != NULL);
  63. _DIAGASSERT(sdl != NULL);
  64. (void)memset(&sdl->sdl_family, 0, (size_t)sdl->sdl_len - 1);
  65. sdl->sdl_family = AF_LINK;
  66. do {
  67. state &= ~LETTER;
  68. if ((*addr >= '0') && (*addr <= '9')) {
  69. newaddr = *addr - '0';
  70. } else if ((*addr >= 'a') && (*addr <= 'f')) {
  71. newaddr = *addr - 'a' + 10;
  72. } else if ((*addr >= 'A') && (*addr <= 'F')) {
  73. newaddr = *addr - 'A' + 10;
  74. } else if (*addr == 0) {
  75. state |= END;
  76. } else if (state == NAMING &&
  77. (((*addr >= 'A') && (*addr <= 'Z')) ||
  78. ((*addr >= 'a') && (*addr <= 'z'))))
  79. state |= LETTER;
  80. else
  81. state |= DELIM;
  82. addr++;
  83. switch (state /* | INPUT */) {
  84. case NAMING | DIGIT:
  85. case NAMING | LETTER:
  86. *cp++ = addr[-1];
  87. continue;
  88. case NAMING | DELIM:
  89. state = RESET;
  90. sdl->sdl_nlen = cp - sdl->sdl_data;
  91. continue;
  92. case GOTTWO | DIGIT:
  93. *cp++ = byte;
  94. /* FALLTHROUGH */
  95. case RESET | DIGIT:
  96. state = GOTONE;
  97. byte = newaddr;
  98. continue;
  99. case GOTONE | DIGIT:
  100. state = GOTTWO;
  101. byte = newaddr + (byte << 4);
  102. continue;
  103. default: /* | DELIM */
  104. state = RESET;
  105. *cp++ = byte;
  106. byte = 0;
  107. continue;
  108. case GOTONE | END:
  109. case GOTTWO | END:
  110. *cp++ = byte;
  111. /* FALLTHROUGH */
  112. case RESET | END:
  113. break;
  114. }
  115. break;
  116. } while (cp < cplim);
  117. sdl->sdl_alen = cp - LLADDR(sdl);
  118. newaddr = cp - (char *)(void *)sdl;
  119. if ((size_t) newaddr > sizeof(*sdl))
  120. sdl->sdl_len = newaddr;
  121. return;
  122. }
  123. static const char hexlist[16] = "0123456789abcdef";
  124. char *
  125. link_ntoa(sdl)
  126. register const struct sockaddr_dl *sdl;
  127. {
  128. static char obuf[64];
  129. register char *out = obuf;
  130. register size_t i;
  131. const u_char *in = (const u_char *)CLLADDR(sdl);
  132. const u_char *inlim = in + sdl->sdl_alen;
  133. int firsttime = 1;
  134. _DIAGASSERT(sdl != NULL);
  135. if (sdl->sdl_nlen) {
  136. (void)memcpy(obuf, sdl->sdl_data, (size_t)sdl->sdl_nlen);
  137. out += sdl->sdl_nlen;
  138. if (sdl->sdl_alen)
  139. *out++ = ':';
  140. }
  141. while (in < inlim) {
  142. if (firsttime)
  143. firsttime = 0;
  144. else
  145. *out++ = '.';
  146. i = *in++;
  147. if (i > 0xf) {
  148. out[1] = hexlist[i & 0xf];
  149. i >>= 4;
  150. out[0] = hexlist[i];
  151. out += 2;
  152. } else
  153. *out++ = hexlist[i];
  154. }
  155. *out = 0;
  156. return (obuf);
  157. }