1/* 2 * $Id: device-bsd44.c,v 1.23 2009/06/19 07:28:06 psavola Exp $ 3 * 4 * Authors: 5 * Craig Metz <cmetz@inner.net> 6 * 7 * This software is Copyright 1996,1997 by the above mentioned author(s), 8 * All Rights Reserved. 9 * 10 * The license which is distributed with this software in the file COPYRIGHT 11 * applies to this software. If your distribution is missing this file, you 12 * may request it from <pekkas@netcore.fi>. 13 * 14 */ 15 16#include <config.h> 17#include <includes.h> 18#include <radvd.h> 19#include <defaults.h> 20#include <pathnames.h> /* for PATH_PROC_NET_IF_INET6 */ 21 22static uint8_t ll_prefix[] = { 0xfe, 0x80 }; 23 24/* 25 * this function gets the hardware type and address of an interface, 26 * determines the link layer token length and checks it against 27 * the defined prefixes 28 */ 29int 30setup_deviceinfo(int sock, struct Interface *iface) 31{ 32 struct ifconf ifconf; 33 struct ifreq ifr; 34 unsigned int nlen; 35 uint8_t *p, *end; 36 struct AdvPrefix *prefix; 37 char zero[sizeof(iface->if_addr)]; 38 39 /* just allocate 8192 bytes, should be more than enough.. */ 40 if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len = (32 << 8)))) 41 { 42 flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); 43 goto ret; 44 } 45 46 if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) 47 { 48 flog(LOG_ERR, "ioctl(SIOCGIFCONF) failed: %s(%d)", strerror(errno), errno); 49 goto ret; 50 } 51 52 memset(&ifr, 0, sizeof(ifr)); 53 strncpy(ifr.ifr_name, iface->Name, IFNAMSIZ-1); 54 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 55 56 if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) { 57 flog(LOG_ERR, "ioctl(SIOCGIFMTU) failed for %s: %s", iface->Name, strerror(errno)); 58 goto ret; 59 } 60 61 dlog(LOG_DEBUG, 3, "mtu for %s is %d", iface->Name, ifr.ifr_mtu); 62 iface->if_maxmtu = ifr.ifr_mtu; 63 64 p = (uint8_t *)ifconf.ifc_buf; 65 end = p + ifconf.ifc_len; 66 nlen = strlen(iface->Name); 67 68 while(p < end) 69 { 70 p += IFNAMSIZ; 71 72 if ((p + 2) >= end) 73 break; 74 75 if ((p + *p) >= end) 76 break; 77 78 if ((*(p + 1) == AF_LINK) && 79 (((struct sockaddr_dl *)p)->sdl_nlen == nlen) && 80 (!memcmp(iface->Name, ((struct sockaddr_dl *)p)->sdl_data, nlen))) 81 { 82 83 if (((struct sockaddr_dl *)p)->sdl_alen > sizeof(iface->if_addr)) 84 { 85 flog(LOG_ERR, "address length %d too big for", 86 ((struct sockaddr_dl *)p)->sdl_alen, 87 iface->Name); 88 goto ret; 89 } 90 91 memcpy(iface->if_hwaddr, LLADDR((struct sockaddr_dl *)p), ((struct sockaddr_dl *)p)->sdl_alen); 92 iface->if_hwaddr_len = ((struct sockaddr_dl *)p)->sdl_alen << 3; 93 94 switch(((struct sockaddr_dl *)p)->sdl_type) { 95 case IFT_ETHER: 96 case IFT_ISO88023: 97 iface->if_prefix_len = 64; 98 break; 99 case IFT_FDDI: 100 iface->if_prefix_len = 64; 101 break; 102 default: 103 iface->if_prefix_len = -1; 104 iface->if_maxmtu = -1; 105 break; 106 } 107 108 dlog(LOG_DEBUG, 3, "link layer token length for %s is %d", iface->Name, 109 iface->if_hwaddr_len); 110 111 dlog(LOG_DEBUG, 3, "prefix length for %s is %d", iface->Name, 112 iface->if_prefix_len); 113 114 if (iface->if_prefix_len != -1) { 115 memset(zero, 0, ((struct sockaddr_dl *)p)->sdl_alen); 116 if (!memcmp(iface->if_hwaddr, zero, ((struct sockaddr_dl *)p)->sdl_alen)) 117 flog(LOG_WARNING, "WARNING, MAC address on %s is all zero!", 118 iface->Name); 119 } 120 121 prefix = iface->AdvPrefixList; 122 while (prefix) 123 { 124 if ((iface->if_prefix_len != -1) && 125 (iface->if_prefix_len != prefix->PrefixLen)) 126 { 127 flog(LOG_WARNING, "prefix length should be %d for %s", 128 iface->if_prefix_len, iface->Name); 129 } 130 131 prefix = prefix->next; 132 } 133 134 free(ifconf.ifc_buf); 135 return 0; 136 } 137 138 p += *p; 139 } 140 141ret: 142 iface->if_maxmtu = -1; 143 iface->if_hwaddr_len = -1; 144 iface->if_prefix_len = -1; 145 free(ifconf.ifc_buf); 146 return -1; 147} 148 149/* 150 * Saves the first link local address seen on the specified interface to iface->if_addr 151 * 152 */ 153int setup_linklocal_addr(int sock, struct Interface *iface) 154{ 155 struct ifaddrs *addresses, *ifa; 156 157 if (getifaddrs(&addresses) != 0) 158 { 159 flog(LOG_ERR, "getifaddrs failed: %s(%d)", strerror(errno), errno); 160 goto ret; 161 } 162 163 for (ifa = addresses; ifa != NULL; ifa = ifa->ifa_next) 164 { 165 if (strcmp(ifa->ifa_name, iface->Name) != 0) 166 continue; 167 168 if (ifa->ifa_addr == NULL) 169 continue; 170 171 if (ifa->ifa_addr->sa_family == AF_LINK) { 172 struct sockaddr_dl *dl = (struct sockaddr_dl*)ifa->ifa_addr; 173 if (memcmp(iface->Name, dl->sdl_data, dl->sdl_nlen) == 0) 174 iface->if_index = dl->sdl_index; 175 continue; 176 } 177 178 if (ifa->ifa_addr->sa_family != AF_INET6) 179 continue; 180 181 struct sockaddr_in6 *a6 = (struct sockaddr_in6*)ifa->ifa_addr; 182 183 /* Skip if it is not a linklocal address */ 184 if (memcmp(&(a6->sin6_addr), ll_prefix, sizeof(ll_prefix)) != 0) 185 continue; 186 187 memcpy(&iface->if_addr, &(a6->sin6_addr), sizeof(struct in6_addr)); 188 freeifaddrs(addresses); 189 return 0; 190 } 191 freeifaddrs(addresses); 192 193ret: 194 flog(LOG_ERR, "no linklocal address configured for %s", iface->Name); 195 return -1; 196} 197 198int setup_allrouters_membership(int sock, struct Interface *iface) 199{ 200 return (0); 201} 202 203int check_allrouters_membership(int sock, struct Interface *iface) 204{ 205 return (0); 206} 207 208int 209set_interface_linkmtu(const char *iface, uint32_t mtu) 210{ 211 dlog(LOG_DEBUG, 4, "setting LinkMTU (%u) for %s is not supported", 212 mtu, iface); 213 return -1; 214} 215 216int 217set_interface_curhlim(const char *iface, uint8_t hlim) 218{ 219 dlog(LOG_DEBUG, 4, "setting CurHopLimit (%u) for %s is not supported", 220 hlim, iface); 221 return -1; 222} 223 224int 225set_interface_reachtime(const char *iface, uint32_t rtime) 226{ 227 dlog(LOG_DEBUG, 4, "setting BaseReachableTime (%u) for %s is not supported", 228 rtime, iface); 229 return -1; 230} 231 232int 233set_interface_retranstimer(const char *iface, uint32_t rettimer) 234{ 235 dlog(LOG_DEBUG, 4, "setting RetransTimer (%u) for %s is not supported", 236 rettimer, iface); 237 return -1; 238} 239 240