if_arcsubr.c revision 109623
1/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */ 2/* $FreeBSD: head/sys/net/if_arcsubr.c 109623 2003-01-21 08:56:16Z alfred $ */ 3 4/* 5 * Copyright (c) 1994, 1995 Ignatios Souvatzis 6 * Copyright (c) 1982, 1989, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp 38 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 39 * 40 */ 41#include "opt_inet.h" 42#include "opt_inet6.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/malloc.h> 48#include <sys/mbuf.h> 49#include <sys/protosw.h> 50#include <sys/socket.h> 51#include <sys/sockio.h> 52#include <sys/errno.h> 53#include <sys/syslog.h> 54 55#include <machine/cpu.h> 56 57#include <net/if.h> 58#include <net/netisr.h> 59#include <net/route.h> 60#include <net/if_dl.h> 61#include <net/if_types.h> 62#include <net/if_arc.h> 63#include <net/if_arp.h> 64#include <net/bpf.h> 65 66#if defined(INET) || defined(INET6) 67#include <netinet/in.h> 68#include <netinet/in_var.h> 69#include <netinet/if_ether.h> 70#endif 71 72#ifdef INET6 73#include <netinet6/nd6.h> 74#endif 75 76MODULE_VERSION(arcnet, 1); 77 78#define ARCNET_ALLOW_BROKEN_ARP 79 80static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 81 82u_int8_t arcbroadcastaddr = 0; 83 84#define senderr(e) { error = (e); goto bad;} 85#define SIN(s) ((struct sockaddr_in *)s) 86 87/* 88 * ARCnet output routine. 89 * Encapsulate a packet of type family for the local net. 90 * Assumes that ifp is actually pointer to arccom structure. 91 */ 92int 93arc_output(ifp, m, dst, rt0) 94 struct ifnet *ifp; 95 struct mbuf *m; 96 struct sockaddr *dst; 97 struct rtentry *rt0; 98{ 99 struct mbuf *mcopy; 100 struct rtentry *rt; 101 struct arccom *ac; 102 struct arc_header *ah; 103 struct arphdr *arph; 104 int error; 105 u_int8_t atype, adst; 106#if __FreeBSD_version < 500000 107 int s; 108#endif 109 110 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 111 return(ENETDOWN); /* m, m1 aren't initialized yet */ 112 113 error = 0; 114 ac = (struct arccom *)ifp; 115 mcopy = NULL; 116 117 if ((rt = rt0)) { 118 if ((rt->rt_flags & RTF_UP) == 0) { 119 if ((rt0 = rt = rtalloc1(dst, 1, 0UL))) 120 rt->rt_refcnt--; 121 else 122 senderr(EHOSTUNREACH); 123 } 124 if (rt->rt_flags & RTF_GATEWAY) { 125 if (rt->rt_gwroute == 0) 126 goto lookup; 127 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 128 rtfree(rt); rt = rt0; 129 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); 130 if ((rt = rt->rt_gwroute) == 0) 131 senderr(EHOSTUNREACH); 132 } 133 } 134 if (rt->rt_flags & RTF_REJECT) 135 if (rt->rt_rmx.rmx_expire == 0 || 136 time_second < rt->rt_rmx.rmx_expire) 137 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 138 } 139 140 switch (dst->sa_family) { 141#ifdef INET 142 case AF_INET: 143 144 /* 145 * For now, use the simple IP addr -> ARCnet addr mapping 146 */ 147 if (m->m_flags & (M_BCAST|M_MCAST)) 148 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 149 else if (ifp->if_flags & IFF_NOARP) 150 adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 151 else if (!arpresolve(ifp, rt, m, dst, &adst, rt0)) 152 return 0; /* not resolved yet */ 153 154 /* If broadcasting on a simplex interface, loopback a copy */ 155 if ((m->m_flags & (M_BCAST|M_MCAST)) && 156 (ifp->if_flags & IFF_SIMPLEX)) 157 mcopy = m_copy(m, 0, (int)M_COPYALL); 158 atype = (ifp->if_flags & IFF_LINK0) ? 159 ARCTYPE_IP_OLD : ARCTYPE_IP; 160 break; 161#endif 162#ifdef INET6 163 case AF_INET6: 164#ifdef OLDIP6OUTPUT 165 if (!nd6_resolve(ifp, rt, m, dst, (u_char *)&adst)) 166 return(0); /* if not yet resolves */ 167#else 168 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)&adst)) 169 return(0); /* it must be impossible, but... */ 170#endif /* OLDIP6OUTPUT */ 171 atype = ARCTYPE_INET6; 172 break; 173#endif 174 175 case AF_UNSPEC: 176 ah = (struct arc_header *)dst->sa_data; 177 adst = ah->arc_dhost; 178 atype = ah->arc_type; 179 180 if (atype == ARCTYPE_ARP) { 181 atype = (ifp->if_flags & IFF_LINK0) ? 182 ARCTYPE_ARP_OLD: ARCTYPE_ARP; 183 184#ifdef ARCNET_ALLOW_BROKEN_ARP 185 /* 186 * XXX It's not clear per RFC826 if this is needed, but 187 * "assigned numbers" say this is wrong. 188 * However, e.g., AmiTCP 3.0Beta used it... we make this 189 * switchable for emergency cases. Not perfect, but... 190 */ 191 arph = mtod(m, struct arphdr *); 192 if (ifp->if_flags & IFF_LINK2) 193 arph->ar_pro = atype - 1; 194#endif 195 } 196 break; 197 198 default: 199 if_printf(ifp, "can't handle af%d\n", dst->sa_family); 200 senderr(EAFNOSUPPORT); 201 } 202 203 if (mcopy) 204 (void) if_simloop(ifp, mcopy, dst->sa_family, 0); 205 206 M_PREPEND(m, ARC_HDRLEN, M_NOWAIT); 207 if (m == 0) 208 senderr(ENOBUFS); 209 ah = mtod(m, struct arc_header *); 210 ah->arc_type = atype; 211 ah->arc_dhost = adst; 212 ah->arc_shost = *IF_LLADDR(ifp); 213 214 BPF_MTAP(ifp, m); 215 216#if __FreeBSD_version < 500000 217 s = splimp(); 218 219 /* 220 * Queue message on interface, and start output if interface 221 * not yet active. 222 */ 223 if (IF_QFULL(&ifp->if_snd)) { 224 IF_DROP(&ifp->if_snd); 225 splx(s); 226 senderr(ENOBUFS); 227 } 228 ifp->if_obytes += m->m_pkthdr.len; 229 IF_ENQUEUE(&ifp->if_snd, m); 230 if ((ifp->if_flags & IFF_OACTIVE) == 0) 231 (*ifp->if_start)(ifp); 232 splx(s); 233#else 234 if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) { 235 m = 0; 236 senderr(ENOBUFS); 237 } 238#endif 239 240 return (error); 241 242bad: 243 if (m) 244 m_freem(m); 245 return (error); 246} 247 248void 249arc_frag_init(ifp) 250 struct ifnet *ifp; 251{ 252 struct arccom *ac; 253 254 ac = (struct arccom *)ifp; 255 ac->curr_frag = 0; 256} 257 258struct mbuf * 259arc_frag_next(ifp) 260 struct ifnet *ifp; 261{ 262 struct arccom *ac; 263 struct mbuf *m; 264 struct arc_header *ah; 265 266 ac = (struct arccom *)ifp; 267 if ((m = ac->curr_frag) == 0) { 268 int tfrags; 269 270 /* dequeue new packet */ 271 IF_DEQUEUE(&ifp->if_snd, m); 272 if (m == 0) 273 return 0; 274 275 ah = mtod(m, struct arc_header *); 276 if (!arc_isphds(ah->arc_type)) 277 return m; 278 279 ++ac->ac_seqid; /* make the seqid unique */ 280 tfrags = (m->m_pkthdr.len + 503) / 504; 281 ac->fsflag = 2 * tfrags - 3; 282 ac->sflag = 0; 283 ac->rsflag = ac->fsflag; 284 ac->arc_dhost = ah->arc_dhost; 285 ac->arc_shost = ah->arc_shost; 286 ac->arc_type = ah->arc_type; 287 288 m_adj(m, ARC_HDRLEN); 289 ac->curr_frag = m; 290 } 291 292 /* split out next fragment and return it */ 293 if (ac->sflag < ac->fsflag) { 294 /* we CAN'T have short packets here */ 295 ac->curr_frag = m_split(m, 504, M_NOWAIT); 296 if (ac->curr_frag == 0) { 297 m_freem(m); 298 return 0; 299 } 300 301 M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 302 if (m == 0) { 303 m_freem(ac->curr_frag); 304 ac->curr_frag = 0; 305 return 0; 306 } 307 308 ah = mtod(m, struct arc_header *); 309 ah->arc_flag = ac->rsflag; 310 ah->arc_seqid = ac->ac_seqid; 311 312 ac->sflag += 2; 313 ac->rsflag = ac->sflag; 314 } else if ((m->m_pkthdr.len >= 315 ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && 316 (m->m_pkthdr.len <= 317 ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { 318 ac->curr_frag = 0; 319 320 M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_NOWAIT); 321 if (m == 0) 322 return 0; 323 324 ah = mtod(m, struct arc_header *); 325 ah->arc_flag = 0xFF; 326 ah->arc_seqid = 0xFFFF; 327 ah->arc_type2 = ac->arc_type; 328 ah->arc_flag2 = ac->sflag; 329 ah->arc_seqid2 = ac->ac_seqid; 330 } else { 331 ac->curr_frag = 0; 332 333 M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 334 if (m == 0) 335 return 0; 336 337 ah = mtod(m, struct arc_header *); 338 ah->arc_flag = ac->sflag; 339 ah->arc_seqid = ac->ac_seqid; 340 } 341 342 ah->arc_dhost = ac->arc_dhost; 343 ah->arc_shost = ac->arc_shost; 344 ah->arc_type = ac->arc_type; 345 346 return m; 347} 348 349/* 350 * Defragmenter. Returns mbuf if last packet found, else 351 * NULL. frees imcoming mbuf as necessary. 352 */ 353 354static __inline struct mbuf * 355arc_defrag(ifp, m) 356 struct ifnet *ifp; 357 struct mbuf *m; 358{ 359 struct arc_header *ah, *ah1; 360 struct arccom *ac; 361 struct ac_frag *af; 362 struct mbuf *m1; 363 char *s; 364 int newflen; 365 u_char src,dst,typ; 366 367 ac = (struct arccom *)ifp; 368 369 if (m->m_len < ARC_HDRNEWLEN) { 370 m = m_pullup(m, ARC_HDRNEWLEN); 371 if (m == NULL) { 372 ++ifp->if_ierrors; 373 return NULL; 374 } 375 } 376 377 ah = mtod(m, struct arc_header *); 378 typ = ah->arc_type; 379 380 if (!arc_isphds(typ)) 381 return m; 382 383 src = ah->arc_shost; 384 dst = ah->arc_dhost; 385 386 if (ah->arc_flag == 0xff) { 387 m_adj(m, 4); 388 389 if (m->m_len < ARC_HDRNEWLEN) { 390 m = m_pullup(m, ARC_HDRNEWLEN); 391 if (m == NULL) { 392 ++ifp->if_ierrors; 393 return NULL; 394 } 395 } 396 397 ah = mtod(m, struct arc_header *); 398 } 399 400 af = &ac->ac_fragtab[src]; 401 m1 = af->af_packet; 402 s = "debug code error"; 403 404 if (ah->arc_flag & 1) { 405 /* 406 * first fragment. We always initialize, which is 407 * about the right thing to do, as we only want to 408 * accept one fragmented packet per src at a time. 409 */ 410 if (m1 != NULL) 411 m_freem(m1); 412 413 af->af_packet = m; 414 m1 = m; 415 af->af_maxflag = ah->arc_flag; 416 af->af_lastseen = 0; 417 af->af_seqid = ah->arc_seqid; 418 419 return NULL; 420 /* notreached */ 421 } else { 422 /* check for unfragmented packet */ 423 if (ah->arc_flag == 0) 424 return m; 425 426 /* do we have a first packet from that src? */ 427 if (m1 == NULL) { 428 s = "no first frag"; 429 goto outofseq; 430 } 431 432 ah1 = mtod(m1, struct arc_header *); 433 434 if (ah->arc_seqid != ah1->arc_seqid) { 435 s = "seqid differs"; 436 goto outofseq; 437 } 438 439 if (typ != ah1->arc_type) { 440 s = "type differs"; 441 goto outofseq; 442 } 443 444 if (dst != ah1->arc_dhost) { 445 s = "dest host differs"; 446 goto outofseq; 447 } 448 449 /* typ, seqid and dst are ok here. */ 450 451 if (ah->arc_flag == af->af_lastseen) { 452 m_freem(m); 453 return NULL; 454 } 455 456 if (ah->arc_flag == af->af_lastseen + 2) { 457 /* ok, this is next fragment */ 458 af->af_lastseen = ah->arc_flag; 459 m_adj(m,ARC_HDRNEWLEN); 460 461 /* 462 * m_cat might free the first mbuf (with pkthdr) 463 * in 2nd chain; therefore: 464 */ 465 466 newflen = m->m_pkthdr.len; 467 468 m_cat(m1,m); 469 470 m1->m_pkthdr.len += newflen; 471 472 /* is it the last one? */ 473 if (af->af_lastseen > af->af_maxflag) { 474 af->af_packet = NULL; 475 return(m1); 476 } else 477 return NULL; 478 } 479 s = "other reason"; 480 /* if all else fails, it is out of sequence, too */ 481 } 482outofseq: 483 if (m1) { 484 m_freem(m1); 485 af->af_packet = NULL; 486 } 487 488 if (m) 489 m_freem(m); 490 491 log(LOG_INFO,"%s%d: got out of seq. packet: %s\n", 492 ifp->if_name, ifp->if_unit, s); 493 494 return NULL; 495} 496 497/* 498 * return 1 if Packet Header Definition Standard, else 0. 499 * For now: old IP, old ARP aren't obviously. Lacking correct information, 500 * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 501 * (Apple and Novell corporations were involved, among others, in PHDS work). 502 * Easiest is to assume that everybody else uses that, too. 503 */ 504int 505arc_isphds(type) 506 u_int8_t type; 507{ 508 return (type != ARCTYPE_IP_OLD && 509 type != ARCTYPE_ARP_OLD && 510 type != ARCTYPE_DIAGNOSE); 511} 512 513/* 514 * Process a received Arcnet packet; 515 * the packet is in the mbuf chain m with 516 * the ARCnet header. 517 */ 518void 519arc_input(ifp, m) 520 struct ifnet *ifp; 521 struct mbuf *m; 522{ 523 struct arc_header *ah; 524 struct ifqueue *inq; 525 u_int8_t atype; 526#ifdef INET 527 struct arphdr *arph; 528#endif 529#if __FreeBSD_version < 500000 530 int s; 531#endif 532 533 if ((ifp->if_flags & IFF_UP) == 0) { 534 m_freem(m); 535 return; 536 } 537 538 /* possibly defragment: */ 539 m = arc_defrag(ifp, m); 540 if (m == NULL) 541 return; 542 543 BPF_MTAP(ifp, m); 544 545 ah = mtod(m, struct arc_header *); 546 547 ifp->if_ibytes += m->m_pkthdr.len; 548 549 if (arcbroadcastaddr == ah->arc_dhost) { 550 m->m_flags |= M_BCAST|M_MCAST; 551 ifp->if_imcasts++; 552 } 553 554 atype = ah->arc_type; 555 switch (atype) { 556#ifdef INET 557 case ARCTYPE_IP: 558 m_adj(m, ARC_HDRNEWLEN); 559 schednetisr(NETISR_IP); 560 inq = &ipintrq; 561 break; 562 563 case ARCTYPE_IP_OLD: 564 m_adj(m, ARC_HDRLEN); 565 schednetisr(NETISR_IP); 566 inq = &ipintrq; 567 break; 568 569 case ARCTYPE_ARP: 570 if (ifp->if_flags & IFF_NOARP) { 571 /* Discard packet if ARP is disabled on interface */ 572 m_freem(m); 573 return; 574 } 575 m_adj(m, ARC_HDRNEWLEN); 576 schednetisr(NETISR_ARP); 577 inq = &arpintrq; 578#ifdef ARCNET_ALLOW_BROKEN_ARP 579 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 580#endif 581 break; 582 583 case ARCTYPE_ARP_OLD: 584 if (ifp->if_flags & IFF_NOARP) { 585 /* Discard packet if ARP is disabled on interface */ 586 m_freem(m); 587 return; 588 } 589 m_adj(m, ARC_HDRLEN); 590 schednetisr(NETISR_ARP); 591 inq = &arpintrq; 592 arph = mtod(m, struct arphdr *); 593#ifdef ARCNET_ALLOW_BROKEN_ARP 594 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 595#endif 596 break; 597#endif 598#ifdef INET6 599 case ARCTYPE_INET6: 600 m_adj(m, ARC_HDRNEWLEN); 601 schednetisr(NETISR_IPV6); 602 inq = &ip6intrq; 603 break; 604#endif 605 default: 606 m_freem(m); 607 return; 608 } 609 610#if __FreeBSD_version < 500000 611 s = splimp(); 612 if (IF_QFULL(inq)) { 613 IF_DROP(inq); 614 m_freem(m); 615 } else 616 IF_ENQUEUE(inq, m); 617 splx(s); 618#else 619 IF_HANDOFF(inq, m, NULL); 620#endif 621} 622 623/* 624 * Convert Arcnet address to printable (loggable) representation. 625 */ 626static char digits[] = "0123456789abcdef"; 627char * 628arc_sprintf(ap) 629 u_int8_t *ap; 630{ 631 static char arcbuf[3]; 632 char *cp = arcbuf; 633 634 *cp++ = digits[*ap >> 4]; 635 *cp++ = digits[*ap++ & 0xf]; 636 *cp = 0; 637 return (arcbuf); 638} 639 640/* 641 * Register (new) link level address. 642 */ 643void 644arc_storelladdr(ifp, lla) 645 struct ifnet *ifp; 646 u_int8_t lla; 647{ 648 *IF_LLADDR(ifp) = lla; 649} 650 651/* 652 * Perform common duties while attaching to interface list 653 */ 654void 655arc_ifattach(ifp, lla) 656 struct ifnet *ifp; 657 u_int8_t lla; 658{ 659 struct ifaddr *ifa; 660 struct sockaddr_dl *sdl; 661 struct arccom *ac; 662 663 if_attach(ifp); 664 ifp->if_type = IFT_ARCNET; 665 ifp->if_addrlen = 1; 666 ifp->if_hdrlen = ARC_HDRLEN; 667 ifp->if_mtu = 1500; 668 if (ifp->if_baudrate == 0) 669 ifp->if_baudrate = 2500000; 670#if __FreeBSD_version < 500000 671 ifa = ifnet_addrs[ifp->if_index - 1]; 672#else 673 ifa = ifaddr_byindex(ifp->if_index); 674#endif 675 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__)); 676 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 677 sdl->sdl_type = IFT_ARCNET; 678 sdl->sdl_alen = ifp->if_addrlen; 679 680 if (ifp->if_flags & IFF_BROADCAST) 681 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 682 683 ac = (struct arccom *)ifp; 684 ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 685 if (lla == 0) { 686 /* XXX this message isn't entirely clear, to me -- cgd */ 687 log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts. Please change it and ifconfig %s%d down up\n", 688 ifp->if_name, ifp->if_unit, ifp->if_name, ifp->if_unit); 689 } 690 arc_storelladdr(ifp, lla); 691 692 ifp->if_broadcastaddr = &arcbroadcastaddr; 693 694 bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 695} 696 697void 698arc_ifdetach(ifp) 699 struct ifnet *ifp; 700{ 701 bpfdetach(ifp); 702 if_detach(ifp); 703} 704 705int 706arc_ioctl(ifp, command, data) 707 struct ifnet *ifp; 708 int command; 709 caddr_t data; 710{ 711 struct ifaddr *ifa = (struct ifaddr *) data; 712 struct ifreq *ifr = (struct ifreq *) data; 713 int error = 0; 714 715 switch (command) { 716 case SIOCSIFADDR: 717 ifp->if_flags |= IFF_UP; 718 switch (ifa->ifa_addr->sa_family) { 719#ifdef INET 720 case AF_INET: 721 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 722 arp_ifinit(ifp, ifa); 723 break; 724#endif 725 default: 726 ifp->if_init(ifp->if_softc); 727 break; 728 } 729 break; 730 731 case SIOCADDMULTI: 732 case SIOCDELMULTI: 733 if (ifr == NULL) 734 error = EAFNOSUPPORT; 735 else { 736 switch (ifr->ifr_addr.sa_family) { 737 case AF_INET: 738 case AF_INET6: 739 error = 0; 740 break; 741 default: 742 error = EAFNOSUPPORT; 743 break; 744 } 745 } 746 break; 747 748 case SIOCSIFMTU: 749 /* 750 * Set the interface MTU. 751 * mtu can't be larger than ARCMTU for RFC1051 752 * and can't be larger than ARC_PHDS_MTU 753 */ 754 if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 755 ifr->ifr_mtu > ARC_PHDS_MAXMTU) 756 error = EINVAL; 757 else 758 ifp->if_mtu = ifr->ifr_mtu; 759 break; 760 761#if 0 762 case SIOCGIFADDR: 763 { 764 struct sockaddr *sa; 765 766 sa = (struct sockaddr *) & ifr->ifr_data; 767 bcopy(IFP2AC(ifp)->ac_enaddr, 768 (caddr_t) sa->sa_data, ETHER_ADDR_LEN); 769 } 770 break; 771#endif 772 } 773 774 return (error); 775} 776