1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <socket_impl.h> 31 #include <socket_inet.h> 32 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/socket.h> 35 #include <net/if.h> 36 #include <net/if_arp.h> 37 #include <net/if_types.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/in.h> 40 #include <netinet/if_ether.h> 41 #include <sys/promif.h> 42 #include <sys/prom_plat.h> 43 #include <sys/salib.h> 44 45 #include "mac.h" 46 #include "mac_impl.h" 47 #include "atm_inet.h" 48 #include "ethernet_inet.h" 49 #include "fddi_inet.h" 50 #include "token_inet.h" 51 #include "ibd_inet.h" 52 53 /* 54 * MAC layer interface 55 */ 56 boolean_t initialized; /* Boolean state */ 57 struct mac_type mac_state; 58 int arp_index; /* current arp table index */ 59 static struct arptable atable[ARP_TABLE_SIZE]; 60 61 #if !defined(__i386) 62 struct ofw_net_types { 63 char *n_name; /* OFW network media name */ 64 int n_type; /* IFT */ 65 } ofw_types[] = { 66 { "atm", IFT_ATM }, 67 { "ethernet", IFT_ETHER }, 68 { "fddi", IFT_FDDI }, 69 { "token-ring", IFT_ISO88025 }, 70 { "ipib", IFT_IB } 71 }; 72 #endif /* !__i386 */ 73 74 /* 75 * given the mac type, initialize the mac interface state. 76 */ 77 void 78 mac_init(char *bootdevicename) 79 { 80 int type = 0; 81 #if !defined(__i386) 82 static char *mtu_name = "max-frame-size"; 83 static char *chosen_net = "chosen-network-type"; 84 static char *supported_net = "supported-network-types"; 85 static char *netiftype = "network-interface-type"; 86 pnode_t node; 87 char *wp, *media_type; 88 int len = 0, i; 89 #endif /* !__i386 */ 90 char tmpbuf[MAXNAMELEN]; 91 char devname[MAXNAMELEN]; 92 93 if (initialized) 94 return; 95 96 mac_state.mac_in_timeout = MAC_IN_TIMEOUT; 97 98 #ifdef DEBUG 99 printf("mac_init: device path: %s\n", bootdevicename); 100 #endif /* DEBUG */ 101 102 if ((mac_state.mac_dev = prom_open(bootdevicename)) == 0) { 103 (void) snprintf(tmpbuf, sizeof (tmpbuf), 104 "Cannot prom_open network device %s.", bootdevicename); 105 prom_panic(tmpbuf); 106 } 107 108 #if !defined(__i386) 109 (void) prom_devname_from_pathname(bootdevicename, devname); 110 #else 111 (void) strcpy(devname, bootdevicename); 112 #endif /* !__i386 */ 113 114 #ifdef DEBUG 115 printf("mac_init: Network device name: %s\n", devname); 116 #endif /* DEBUG */ 117 118 #if !defined(__i386) 119 /* 120 * Ask the prom for our MTU and media type. "chosen-network-type" 121 * is of the form of "<network type>,<speed (Mbps)>,<connector type>, 122 * <duplex mode>: e.g.: "ethernet,100,rj45,full" 123 */ 124 node = prom_finddevice(devname); 125 if (node != OBP_NONODE && node != OBP_BADNODE) { 126 if (prom_getproplen(node, mtu_name) == sizeof (ihandle_t)) { 127 (void) prom_getprop(node, mtu_name, 128 (caddr_t)&mac_state.mac_mtu); 129 } 130 bzero(tmpbuf, sizeof (tmpbuf)); 131 /* 132 * The following order of looking for properties is 133 * from FWARC 2002/345. 134 */ 135 if ((len = prom_getproplen(node, netiftype)) > 0 && 136 len < sizeof (tmpbuf)) { 137 (void) prom_getprop(node, netiftype, tmpbuf); 138 } else if ((len = prom_getproplen(node, chosen_net)) > 0 && 139 len < sizeof (tmpbuf)) { 140 (void) prom_getprop(node, chosen_net, tmpbuf); 141 } else if ((len = prom_getproplen(node, supported_net)) > 0 && 142 len < sizeof (tmpbuf)) { 143 (void) prom_getprop(node, supported_net, tmpbuf); 144 } 145 media_type = NULL; 146 if (len > 0) { 147 if ((wp = strstr(tmpbuf, ",")) != NULL) 148 *wp = '\0'; 149 media_type = tmpbuf; 150 } 151 if (media_type != NULL) { 152 #ifdef DEBUG 153 printf("mac_init: Media type: %s\n", media_type); 154 #endif /* DEBUG */ 155 for (i = 0; i < sizeof (ofw_types) / 156 sizeof (struct ofw_net_types); i++) { 157 if (strcmp(ofw_types[i].n_name, 158 media_type) == 0) { 159 type = ofw_types[i].n_type; 160 break; 161 } 162 } 163 } 164 } 165 #else 166 type = IFT_ETHER; /* default to ethernet */ 167 #endif /* !__i386 */ 168 169 switch (type) { 170 case IFT_ATM: 171 /* 172 * ATM is currently treated mostly like ethernet, 173 * with the exception that the MTU is most likely 174 * different. 175 */ 176 mac_state.mac_type = IFT_ATM; 177 mac_state.mac_arp_timeout = ATM_ARP_TIMEOUT; 178 mac_state.mac_in_timeout = ATM_IN_TIMEOUT; 179 if (mac_state.mac_mtu == 0) 180 mac_state.mac_mtu = ATMSIZE; 181 mac_state.mac_addr_len = sizeof (ether_addr_t); 182 mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len); 183 if (mac_state.mac_addr_buf == NULL) 184 prom_panic("mac_init: Cannot allocate memory."); 185 if (prom_getmacaddr(mac_state.mac_dev, 186 (caddr_t)mac_state.mac_addr_buf) != 0) 187 prom_panic("mac_init: Cannot obtain MAC address."); 188 mac_state.mac_arp = ether_arp; 189 mac_state.mac_rarp = ether_revarp; 190 mac_state.mac_header_len = ether_header_len; 191 mac_state.mac_input = ether_input; 192 mac_state.mac_output = ether_output; 193 break; 194 195 case IFT_FDDI: 196 /* 197 * FDDI is currently treated mostly like ethernet, 198 * with the exception that the MTU is most likely 199 * different. 200 */ 201 mac_state.mac_type = IFT_FDDI; 202 mac_state.mac_arp_timeout = FDDI_ARP_TIMEOUT; 203 mac_state.mac_in_timeout = FDDI_IN_TIMEOUT; 204 if (mac_state.mac_mtu == 0) 205 mac_state.mac_mtu = FDDISIZE; 206 mac_state.mac_addr_len = sizeof (ether_addr_t); 207 mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len); 208 if (mac_state.mac_addr_buf == NULL) 209 prom_panic("mac_init: Cannot allocate memory."); 210 if (prom_getmacaddr(mac_state.mac_dev, 211 (caddr_t)mac_state.mac_addr_buf) != 0) 212 prom_panic("mac_init: Cannot obtain MAC address."); 213 mac_state.mac_arp = ether_arp; 214 mac_state.mac_rarp = ether_revarp; 215 mac_state.mac_header_len = ether_header_len; 216 mac_state.mac_input = ether_input; 217 mac_state.mac_output = ether_output; 218 break; 219 220 case IFT_ISO88025: 221 /* 222 * Token ring is currently treated mostly like ethernet, 223 * with the exception that the MTU is most likely different. 224 */ 225 mac_state.mac_type = IFT_ISO88025; 226 mac_state.mac_arp_timeout = TOKEN_ARP_TIMEOUT; 227 mac_state.mac_in_timeout = TOKEN_IN_TIMEOUT; 228 if (mac_state.mac_mtu == 0) 229 mac_state.mac_mtu = TOKENSIZE; 230 mac_state.mac_addr_len = sizeof (ether_addr_t); 231 mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len); 232 if (mac_state.mac_addr_buf == NULL) 233 prom_panic("mac_init: Cannot allocate memory."); 234 if (prom_getmacaddr(mac_state.mac_dev, 235 (caddr_t)mac_state.mac_addr_buf) != 0) 236 prom_panic("mac_init: Cannot obtain MAC address."); 237 mac_state.mac_arp = ether_arp; 238 mac_state.mac_rarp = ether_revarp; 239 mac_state.mac_header_len = ether_header_len; 240 mac_state.mac_input = ether_input; 241 mac_state.mac_output = ether_output; 242 break; 243 244 case IFT_IB: 245 mac_state.mac_type = IFT_IB; 246 ibd_init(); 247 break; 248 249 case IFT_ETHER: 250 /* FALLTHRU - default to ethernet */ 251 default: 252 mac_state.mac_type = IFT_ETHER; 253 mac_state.mac_mtu = ETHERSIZE; 254 mac_state.mac_arp_timeout = ETHER_ARP_TIMEOUT; 255 mac_state.mac_in_timeout = ETHER_IN_TIMEOUT; 256 if (mac_state.mac_mtu == 0) 257 mac_state.mac_mtu = ETHERSIZE; 258 mac_state.mac_addr_len = sizeof (ether_addr_t); 259 mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len); 260 if (mac_state.mac_addr_buf == NULL) 261 prom_panic("mac_init: Cannot allocate memory."); 262 if (prom_getmacaddr(mac_state.mac_dev, 263 (caddr_t)mac_state.mac_addr_buf) != 0) 264 prom_panic("mac_init: Cannot obtain MAC address."); 265 mac_state.mac_arp = ether_arp; 266 mac_state.mac_rarp = ether_revarp; 267 mac_state.mac_header_len = ether_header_len; 268 mac_state.mac_input = ether_input; 269 mac_state.mac_output = ether_output; 270 break; 271 } 272 273 mac_state.mac_buf = bkmem_alloc(mac_state.mac_mtu); 274 if (mac_state.mac_buf == NULL) 275 prom_panic("mac_init: Cannot allocate netbuf memory."); 276 else 277 initialized = B_TRUE; 278 } 279 280 void 281 mac_fini() 282 { 283 if (mac_state.mac_addr_buf != NULL) { 284 bkmem_free((caddr_t)mac_state.mac_addr_buf, 285 mac_state.mac_addr_len); 286 mac_state.mac_addr_buf = NULL; 287 } 288 if (mac_state.mac_buf != NULL) { 289 bkmem_free(mac_state.mac_buf, mac_state.mac_mtu); 290 mac_state.mac_buf = NULL; 291 } 292 (void) prom_close(mac_state.mac_dev); 293 initialized = B_FALSE; 294 } 295 296 /* MAC layer specific socket initialization */ 297 void 298 mac_socket_init(struct inetboot_socket *isp) 299 { 300 isp->input[MEDIA_LVL] = mac_state.mac_input; 301 isp->output[MEDIA_LVL] = mac_state.mac_output; 302 isp->close[MEDIA_LVL] = NULL; 303 isp->headerlen[MEDIA_LVL] = mac_state.mac_header_len; 304 isp->in_timeout = mac_state.mac_in_timeout; 305 } 306 307 /* 308 * Add an entry to the ARP table. All values in table are network order. 309 * No checking is done to determine whether there's duplicates. 310 */ 311 void 312 mac_set_arp(struct in_addr *ip, void *hp, int hl) 313 { 314 atable[arp_index].ia.s_addr = ip->s_addr; 315 bcopy(hp, (char *)atable[arp_index].ha, hl); 316 atable[arp_index].hl = hl; 317 arp_index++; 318 if (arp_index >= ARP_TABLE_SIZE) 319 arp_index = 0; 320 } 321 322 /* 323 * Retrieve an entry from the ARP table using network-order IP address as 324 * search criteria. HW address buffer is filled in up to hl in len. (make 325 * sure the buffer is big enough given the mac type) 326 * 327 * Returns TRUE if successful, FALSE otherwise. Will wait timeout milliseconds 328 * for a response. 329 */ 330 int 331 mac_get_arp(struct in_addr *ip, void *hp, int hl, uint32_t timeout) 332 { 333 int i, result; 334 335 for (i = 0; i < ARP_TABLE_SIZE; i++) { 336 if (ip->s_addr == atable[i].ia.s_addr) { 337 bcopy((char *)atable[i].ha, hp, hl); 338 return (TRUE); 339 } 340 } 341 342 /* Not found. ARP for it. */ 343 bzero(hp, hl); 344 result = mac_state.mac_arp(ip, hp, timeout); 345 346 if (result) { 347 /* Cool - add it to the arp table */ 348 mac_set_arp(ip, hp, hl); 349 } 350 return (result); 351 } 352 353 int 354 mac_get_mtu(void) 355 { 356 if (!initialized) 357 return (-1); 358 else 359 return (mac_state.mac_mtu); 360 } 361 362 int 363 mac_get_dev(void) 364 { 365 if (!initialized) 366 return (-1); 367 else 368 return (mac_state.mac_dev); 369 } 370 371 uint8_t * 372 mac_get_addr_buf(void) 373 { 374 if (!initialized) 375 return (NULL); 376 else 377 return (mac_state.mac_addr_buf); 378 } 379 380 int 381 mac_get_addr_len(void) 382 { 383 if (!initialized) 384 return (-1); 385 else 386 return (mac_state.mac_addr_len); 387 } 388 389 int 390 mac_get_type(void) 391 { 392 if (!initialized) 393 return (-1); 394 else 395 return (mac_state.mac_type); 396 } 397 398 int 399 mac_get_arp_timeout(void) 400 { 401 if (!initialized) 402 return (-1); 403 else 404 return (mac_state.mac_arp_timeout); 405 } 406 407 int 408 mac_get_hdr_len(void) 409 { 410 if (!initialized) 411 return (-1); 412 else 413 return (mac_state.mac_header_len(NULL)); 414 } 415 416 int 417 mac_call_arp(struct in_addr *addr, void *buf, uint32_t timeout) 418 { 419 return (mac_state.mac_arp(addr, buf, timeout)); 420 } 421 422 void 423 mac_call_rarp(void) 424 { 425 mac_state.mac_rarp(); 426 } 427 428 /* 429 * Map a IFT_ type to an RFC 1700 arp hwtype. 430 */ 431 uint8_t 432 mac_arp_type(uint8_t ift_type) 433 { 434 uint8_t arptype; 435 436 switch (ift_type) { 437 case IFT_ISO88025: 438 arptype = 4; /* token ring */ 439 break; 440 case IFT_ATM: 441 arptype = 16; /* ATM */ 442 break; 443 case IFT_FDDI: 444 arptype = 18; /* Fiber Channel */ 445 break; 446 case IFT_IB: 447 arptype = 32; /* Infiniband */ 448 break; 449 case IFT_ETHER: 450 /* FALLTHRU */ 451 default: 452 arptype = 1; /* default to ethernet */ 453 break; 454 } 455 return (arptype); 456 } 457