if_atmsubr.c revision 112193
125603Skjc/* $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck Exp $ */ 225603Skjc 325603Skjc/* 425603Skjc * 525603Skjc * Copyright (c) 1996 Charles D. Cranor and Washington University. 625603Skjc * All rights reserved. 725603Skjc * 825603Skjc * Redistribution and use in source and binary forms, with or without 925603Skjc * modification, are permitted provided that the following conditions 1025603Skjc * are met: 1125603Skjc * 1. Redistributions of source code must retain the above copyright 1225603Skjc * notice, this list of conditions and the following disclaimer. 1325603Skjc * 2. Redistributions in binary form must reproduce the above copyright 1425603Skjc * notice, this list of conditions and the following disclaimer in the 1525603Skjc * documentation and/or other materials provided with the distribution. 1625603Skjc * 3. All advertising materials mentioning features or use of this software 1725603Skjc * must display the following acknowledgement: 1825603Skjc * This product includes software developed by Charles D. Cranor and 1925603Skjc * Washington University. 2025603Skjc * 4. The name of the author may not be used to endorse or promote products 2125603Skjc * derived from this software without specific prior written permission. 2225603Skjc * 2325603Skjc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2425603Skjc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2525603Skjc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2625603Skjc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2725603Skjc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2825603Skjc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2925603Skjc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3025603Skjc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3125603Skjc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3225603Skjc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3354263Sshin * 3454263Sshin * $FreeBSD: head/sys/net/if_atmsubr.c 112193 2003-03-13 12:44:06Z harti $ 3525603Skjc */ 3625603Skjc 3725603Skjc/* 3825603Skjc * if_atmsubr.c 3925603Skjc */ 4025603Skjc 4132350Seivind#include "opt_inet.h" 4254263Sshin#include "opt_inet6.h" 43105576Srwatson#include "opt_mac.h" 4432925Seivind#include "opt_natm.h" 4532350Seivind 4625603Skjc#include <sys/param.h> 4725603Skjc#include <sys/systm.h> 48105576Srwatson#include <sys/mac.h> 4925603Skjc#include <sys/mbuf.h> 5025603Skjc#include <sys/socket.h> 5137939Skjc#include <sys/sockio.h> 5237939Skjc#include <sys/errno.h> 5325603Skjc 5425603Skjc#include <net/if.h> 5525603Skjc#include <net/netisr.h> 5625603Skjc#include <net/route.h> 5725603Skjc#include <net/if_dl.h> 5825603Skjc#include <net/if_types.h> 5925603Skjc#include <net/if_atm.h> 6025603Skjc 6125603Skjc#include <netinet/in.h> 6225603Skjc#include <netinet/if_atm.h> 6325603Skjc#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */ 6437939Skjc#if defined(INET) || defined(INET6) 6525603Skjc#include <netinet/in_var.h> 6625603Skjc#endif 6725603Skjc#ifdef NATM 6825603Skjc#include <netnatm/natm.h> 6925603Skjc#endif 7025603Skjc 7137939Skjc#ifndef ETHERTYPE_IPV6 7237939Skjc#define ETHERTYPE_IPV6 0x86dd 7337939Skjc#endif 7425603Skjc 7525603Skjc#define senderr(e) { error = (e); goto bad;} 7625603Skjc 7725603Skjc/* 7825603Skjc * atm_output: ATM output routine 7925603Skjc * inputs: 8025603Skjc * "ifp" = ATM interface to output to 8125603Skjc * "m0" = the packet to output 8225603Skjc * "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI) 8325603Skjc * "rt0" = the route to use 8425603Skjc * returns: error code [0 == ok] 8525603Skjc * 8625603Skjc * note: special semantic: if (dst == NULL) then we assume "m" already 8725603Skjc * has an atm_pseudohdr on it and just send it directly. 8825603Skjc * [for native mode ATM output] if dst is null, then 8925603Skjc * rt0 must also be NULL. 9025603Skjc */ 9125603Skjc 9225603Skjcint 9325603Skjcatm_output(ifp, m0, dst, rt0) 94111774Smdodd struct ifnet *ifp; 9525603Skjc struct mbuf *m0; 9625603Skjc struct sockaddr *dst; 9725603Skjc struct rtentry *rt0; 9825603Skjc{ 9925603Skjc u_int16_t etype = 0; /* if using LLC/SNAP */ 10078249Speter int error = 0, sz; 10125603Skjc struct atm_pseudohdr atmdst, *ad; 10259633Skjc struct mbuf *m = m0; 10359633Skjc struct rtentry *rt; 10425603Skjc struct atmllc *atmllc; 10537939Skjc struct atmllc *llc_hdr = NULL; 10625603Skjc u_int32_t atm_flags; 10725603Skjc 108105576Srwatson#ifdef MAC 109105576Srwatson error = mac_check_ifnet_transmit(ifp, m); 110105576Srwatson if (error) 111105576Srwatson senderr(error); 112105576Srwatson#endif 113105576Srwatson 11425603Skjc if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 11525603Skjc senderr(ENETDOWN); 11625603Skjc 11725603Skjc /* 11825603Skjc * check route 11925603Skjc */ 120111767Smdodd error = rt_check(&rt, &rt0, dst); 121111767Smdodd if (error) 122111767Smdodd goto bad; 12325603Skjc 12425603Skjc /* 12525603Skjc * check for non-native ATM traffic (dst != NULL) 12625603Skjc */ 12725603Skjc if (dst) { 12825603Skjc switch (dst->sa_family) { 12937939Skjc#if defined(INET) || defined(INET6) 13025603Skjc case AF_INET: 13137939Skjc case AF_INET6: 13246695Skjc if (dst->sa_family == AF_INET6) 133112193Sharti etype = ETHERTYPE_IPV6; 13446695Skjc else 135112193Sharti etype = ETHERTYPE_IP; 13625603Skjc if (!atmresolve(rt, m, dst, &atmdst)) { 13725603Skjc m = NULL; 13825603Skjc /* XXX: atmresolve already free'd it */ 13925603Skjc senderr(EHOSTUNREACH); 14025603Skjc /* XXX: put ATMARP stuff here */ 14125603Skjc /* XXX: watch who frees m on failure */ 14225603Skjc } 14325603Skjc break; 14437939Skjc#endif /* INET || INET6 */ 14525603Skjc 14637939Skjc case AF_UNSPEC: 14737939Skjc /* 14846695Skjc * XXX: bpfwrite. assuming dst contains 12 bytes 14946695Skjc * (atm pseudo header (4) + LLC/SNAP (8)) 15037939Skjc */ 15137939Skjc bcopy(dst->sa_data, &atmdst, sizeof(atmdst)); 15237939Skjc llc_hdr = (struct atmllc *)(dst->sa_data + sizeof(atmdst)); 15337939Skjc break; 15437939Skjc 15525603Skjc default: 15625603Skjc#if defined(__NetBSD__) || defined(__OpenBSD__) 15725603Skjc printf("%s: can't handle af%d\n", ifp->if_xname, 15825603Skjc dst->sa_family); 15925603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__) 16025603Skjc printf("%s%d: can't handle af%d\n", ifp->if_name, 16125603Skjc ifp->if_unit, dst->sa_family); 16225603Skjc#endif 16325603Skjc senderr(EAFNOSUPPORT); 16425603Skjc } 16525603Skjc 16625603Skjc /* 16725603Skjc * must add atm_pseudohdr to data 16825603Skjc */ 16925603Skjc sz = sizeof(atmdst); 17025603Skjc atm_flags = ATM_PH_FLAGS(&atmdst); 17125603Skjc if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */ 172111119Simp M_PREPEND(m, sz, M_DONTWAIT); 17325603Skjc if (m == 0) 17425603Skjc senderr(ENOBUFS); 17525603Skjc ad = mtod(m, struct atm_pseudohdr *); 17625603Skjc *ad = atmdst; 17725603Skjc if (atm_flags & ATM_PH_LLCSNAP) { 17825603Skjc atmllc = (struct atmllc *)(ad + 1); 17937939Skjc if (llc_hdr == NULL) { 18037939Skjc bcopy(ATMLLC_HDR, atmllc->llchdr, 18137939Skjc sizeof(atmllc->llchdr)); 18237939Skjc ATM_LLC_SETTYPE(atmllc, etype); 183112193Sharti /* note: in host order */ 18437939Skjc } 18537939Skjc else 18637939Skjc bcopy(llc_hdr, atmllc, sizeof(struct atmllc)); 18725603Skjc } 18825603Skjc } 18925603Skjc 19025603Skjc /* 19125603Skjc * Queue message on interface, and start output if interface 19225603Skjc * not yet active. 19325603Skjc */ 19469152Sjlemon if (! IF_HANDOFF(&ifp->if_snd, m, ifp)) 19569152Sjlemon return (ENOBUFS); 19625603Skjc return (error); 19725603Skjc 19825603Skjcbad: 19925603Skjc if (m) 20025603Skjc m_freem(m); 20125603Skjc return (error); 20225603Skjc} 20325603Skjc 20425603Skjc/* 20525603Skjc * Process a received ATM packet; 20625603Skjc * the packet is in the mbuf chain m. 20725603Skjc */ 20825603Skjcvoid 20925603Skjcatm_input(ifp, ah, m, rxhand) 21025603Skjc struct ifnet *ifp; 211111774Smdodd struct atm_pseudohdr *ah; 21225603Skjc struct mbuf *m; 21325603Skjc void *rxhand; 21425603Skjc{ 215111888Sjlemon int isr; 21625603Skjc u_int16_t etype = ETHERTYPE_IP; /* default */ 21725603Skjc int s; 21825603Skjc 21925603Skjc if ((ifp->if_flags & IFF_UP) == 0) { 22025603Skjc m_freem(m); 22125603Skjc return; 22225603Skjc } 223105576Srwatson#ifdef MAC 224105576Srwatson mac_create_mbuf_from_ifnet(ifp, m); 225105576Srwatson#endif 22625603Skjc ifp->if_ibytes += m->m_pkthdr.len; 22725603Skjc 22825603Skjc if (rxhand) { 22925603Skjc#ifdef NATM 23037939Skjc struct natmpcb *npcb = rxhand; 23137939Skjc s = splimp(); /* in case 2 atm cards @ diff lvls */ 23237939Skjc npcb->npcb_inq++; /* count # in queue */ 23337939Skjc splx(s); 234111888Sjlemon isr = NETISR_NATM; 23537939Skjc m->m_pkthdr.rcvif = rxhand; /* XXX: overload */ 23625603Skjc#else 23737939Skjc printf("atm_input: NATM detected but not configured in kernel\n"); 23837939Skjc m_freem(m); 23937939Skjc return; 24025603Skjc#endif 24125603Skjc } else { 24237939Skjc /* 24337939Skjc * handle LLC/SNAP header, if present 24437939Skjc */ 24537939Skjc if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) { 24637939Skjc struct atmllc *alc; 24737939Skjc if (m->m_len < sizeof(*alc) && 24837939Skjc (m = m_pullup(m, sizeof(*alc))) == 0) 24937939Skjc return; /* failed */ 25037939Skjc alc = mtod(m, struct atmllc *); 25137939Skjc if (bcmp(alc, ATMLLC_HDR, 6)) { 25225603Skjc#if defined(__NetBSD__) || defined(__OpenBSD__) 25337939Skjc printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n", 25437939Skjc ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah)); 25525603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__) 25637939Skjc printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n", 25737939Skjc ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah)); 25825603Skjc#endif 25937939Skjc m_freem(m); 26037939Skjc return; 26137939Skjc } 26237939Skjc etype = ATM_LLC_TYPE(alc); 26337939Skjc m_adj(m, sizeof(*alc)); 26437939Skjc } 26525603Skjc 26637939Skjc switch (etype) { 26725603Skjc#ifdef INET 26837939Skjc case ETHERTYPE_IP: 269111888Sjlemon isr = NETISR_IP; 27037939Skjc break; 27125603Skjc#endif 27237939Skjc#ifdef INET6 27337939Skjc case ETHERTYPE_IPV6: 274111888Sjlemon isr = NETISR_IPV6; 27537939Skjc break; 27637939Skjc#endif 27737939Skjc default: 27837939Skjc m_freem(m); 27937939Skjc return; 28037939Skjc } 28125603Skjc } 282111888Sjlemon netisr_dispatch(isr, m); 28325603Skjc} 28425603Skjc 28525603Skjc/* 28625603Skjc * Perform common duties while attaching to interface list 28725603Skjc */ 28825603Skjcvoid 28925603Skjcatm_ifattach(ifp) 290111774Smdodd struct ifnet *ifp; 29125603Skjc{ 292111774Smdodd struct ifaddr *ifa; 293111774Smdodd struct sockaddr_dl *sdl; 29425603Skjc 29525603Skjc ifp->if_type = IFT_ATM; 29625603Skjc ifp->if_addrlen = 0; 29725603Skjc ifp->if_hdrlen = 0; 29825603Skjc ifp->if_mtu = ATMMTU; 29925603Skjc ifp->if_output = atm_output; 300106939Ssam#if 0 301106939Ssam ifp->if_input = atm_input; 302106939Ssam#endif 30346695Skjc ifp->if_snd.ifq_maxlen = 50; /* dummy */ 30425603Skjc 30525603Skjc#if defined(__NetBSD__) || defined(__OpenBSD__) 30672012Sphk TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) 30737939Skjc#elif defined(__FreeBSD__) && (__FreeBSD__ > 2) 30871959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 30971959Sphk ifa = TAILQ_NEXT(ifa, ifa_link)) 31025603Skjc#elif defined(__FreeBSD__) || defined(__bsdi__) 31125603Skjc for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31225603Skjc#endif 31325603Skjc if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 31425603Skjc sdl->sdl_family == AF_LINK) { 31525603Skjc sdl->sdl_type = IFT_ATM; 31625603Skjc sdl->sdl_alen = ifp->if_addrlen; 31725603Skjc#ifdef notyet /* if using ATMARP, store hardware address using the next line */ 31825603Skjc bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen); 31925603Skjc#endif 32025603Skjc break; 32125603Skjc } 32237939Skjc 32337939Skjc} 324