125603Skjc/* $NetBSD: if_atm.c,v 1.6 1996/10/13 02:03:01 christos Exp $ */ 225603Skjc 3139823Simp/*- 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: 18133874Srwatson * This product includes software developed by Charles D. Cranor and 19133874Srwatson * 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. 3325603Skjc */ 34118497Sharti#include <sys/cdefs.h> 35118497Sharti__FBSDID("$FreeBSD$"); 3625603Skjc 3725603Skjc/* 3825603Skjc * IP <=> ATM address resolution. 3925603Skjc */ 4032350Seivind#include "opt_inet.h" 4154263Sshin#include "opt_inet6.h" 4232925Seivind#include "opt_natm.h" 4332350Seivind 4437939Skjc#if defined(INET) || defined(INET6) 4525603Skjc 4625603Skjc#include <sys/param.h> 4725603Skjc#include <sys/systm.h> 4837939Skjc#include <sys/queue.h> 4925603Skjc#include <sys/mbuf.h> 5025603Skjc#include <sys/socket.h> 5125603Skjc#include <sys/sockio.h> 5225603Skjc#include <sys/syslog.h> 5325603Skjc 5425603Skjc#include <net/if.h> 5525603Skjc#include <net/if_dl.h> 5625603Skjc#include <net/route.h> 5725603Skjc#include <net/if_atm.h> 5825603Skjc 5925603Skjc#include <netinet/in.h> 6025603Skjc#include <netinet/if_atm.h> 6125603Skjc 6225603Skjc#ifdef NATM 6325603Skjc#include <netnatm/natm.h> 6425603Skjc#endif 6525603Skjc 6625603Skjc#define SDL(s) ((struct sockaddr_dl *)s) 6725603Skjc 68118823Sharti#define GET3BYTE(V, A, L) do { \ 69118823Sharti (V) = ((A)[0] << 16) | ((A)[1] << 8) | (A)[2]; \ 70118823Sharti (A) += 3; \ 71118823Sharti (L) -= 3; \ 72118823Sharti } while (0) 73118823Sharti 74118823Sharti#define GET2BYTE(V, A, L) do { \ 75118823Sharti (V) = ((A)[0] << 8) | (A)[1]; \ 76118823Sharti (A) += 2; \ 77118823Sharti (L) -= 2; \ 78118823Sharti } while (0) 79118823Sharti 80118823Sharti#define GET1BYTE(V, A, L) do { \ 81118823Sharti (V) = *(A)++; \ 82118823Sharti (L)--; \ 83118823Sharti } while (0) 84118823Sharti 85118823Sharti 8625603Skjc/* 8725603Skjc * atm_rtrequest: handle ATM rt request (in support of generic code) 8825603Skjc * inputs: "req" = request code 8925603Skjc * "rt" = route entry 9085074Sru * "info" = rt_addrinfo 9125603Skjc */ 9225603Skjcvoid 93118497Shartiatm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) 9425603Skjc{ 95118497Sharti struct sockaddr *gate = rt->rt_gateway; 96118552Sharti struct atmio_openvcc op; 97118552Sharti struct atmio_closevcc cl; 98118552Sharti u_char *addr; 99118552Sharti u_int alen; 10025603Skjc#ifdef NATM 10125603Skjc struct sockaddr_in *sin; 10225603Skjc struct natmpcb *npcb = NULL; 10325603Skjc#endif 10425603Skjc static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; 10525603Skjc 10625603Skjc if (rt->rt_flags & RTF_GATEWAY) /* link level requests only */ 10725603Skjc return; 10825603Skjc 10925603Skjc switch (req) { 11025603Skjc 11125603Skjc case RTM_RESOLVE: /* resolve: only happens when cloning */ 11225603Skjc printf("atm_rtrequest: RTM_RESOLVE request detected?\n"); 11325603Skjc break; 11425603Skjc 11525603Skjc case RTM_ADD: 11625603Skjc /* 11725603Skjc * route added by a command (e.g. ifconfig, route, arp...). 11825603Skjc * 11925603Skjc * first check to see if this is not a host route, in which 12025603Skjc * case we are being called via "ifconfig" to set the address. 12125603Skjc */ 122133874Srwatson if ((rt->rt_flags & RTF_HOST) == 0) { 12325603Skjc rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl); 12425603Skjc gate = rt->rt_gateway; 12525603Skjc SDL(gate)->sdl_type = rt->rt_ifp->if_type; 12625603Skjc SDL(gate)->sdl_index = rt->rt_ifp->if_index; 12725603Skjc break; 12825603Skjc } 12925603Skjc 13025603Skjc if (gate->sa_family != AF_LINK || 13125603Skjc gate->sa_len < sizeof(null_sdl)) { 13225603Skjc log(LOG_DEBUG, "atm_rtrequest: bad gateway value"); 13325603Skjc break; 13425603Skjc } 13525603Skjc 13697074Sarr KASSERT(rt->rt_ifp->if_ioctl != NULL, 13797074Sarr ("atm_rtrequest: null ioctl")); 138118552Sharti 139118552Sharti /* 140118552Sharti * Parse and verify the link level address as 141118552Sharti * an open request 142118552Sharti */ 143148980Srodrigc#ifdef NATM 144148980Srodrigc NATM_LOCK(); 145148980Srodrigc#endif 146118552Sharti bzero(&op, sizeof(op)); 147118552Sharti addr = LLADDR(SDL(gate)); 148118552Sharti alen = SDL(gate)->sdl_alen; 149118552Sharti if (alen < 4) { 150118552Sharti printf("%s: bad link-level address\n", __func__); 151118552Sharti goto failed; 152118552Sharti } 153118552Sharti 154118552Sharti if (alen == 4) { 155118552Sharti /* old type address */ 156118823Sharti GET1BYTE(op.param.flags, addr, alen); 157118823Sharti GET1BYTE(op.param.vpi, addr, alen); 158118823Sharti GET2BYTE(op.param.vci, addr, alen); 159118552Sharti op.param.traffic = ATMIO_TRAFFIC_UBR; 160118552Sharti op.param.aal = (op.param.flags & ATM_PH_AAL5) ? 161118552Sharti ATMIO_AAL_5 : ATMIO_AAL_0; 162118552Sharti } else { 163118552Sharti /* new address */ 164118552Sharti op.param.aal = ATMIO_AAL_5; 165118823Sharti 166118823Sharti GET1BYTE(op.param.flags, addr, alen); 167118823Sharti op.param.flags &= ATM_PH_LLCSNAP; 168118823Sharti 169118823Sharti GET1BYTE(op.param.vpi, addr, alen); 170118823Sharti GET2BYTE(op.param.vci, addr, alen); 171118823Sharti 172118823Sharti GET1BYTE(op.param.traffic, addr, alen); 173118823Sharti 174118552Sharti switch (op.param.traffic) { 175118552Sharti 176118552Sharti case ATMIO_TRAFFIC_UBR: 177118823Sharti if (alen >= 3) 178118823Sharti GET3BYTE(op.param.tparam.pcr, 179118823Sharti addr, alen); 180118552Sharti break; 181118552Sharti 182118552Sharti case ATMIO_TRAFFIC_CBR: 183118552Sharti if (alen < 3) 184118552Sharti goto bad_param; 185118823Sharti GET3BYTE(op.param.tparam.pcr, addr, alen); 186118552Sharti break; 187118552Sharti 188118552Sharti case ATMIO_TRAFFIC_VBR: 189118552Sharti if (alen < 3 * 3) 190118552Sharti goto bad_param; 191118823Sharti GET3BYTE(op.param.tparam.pcr, addr, alen); 192118823Sharti GET3BYTE(op.param.tparam.scr, addr, alen); 193118823Sharti GET3BYTE(op.param.tparam.mbs, addr, alen); 194118552Sharti break; 195118552Sharti 196118552Sharti case ATMIO_TRAFFIC_ABR: 197118823Sharti if (alen < 4 * 3 + 2 + 1 * 2 + 3) 198118552Sharti goto bad_param; 199118823Sharti GET3BYTE(op.param.tparam.pcr, addr, alen); 200118823Sharti GET3BYTE(op.param.tparam.mcr, addr, alen); 201118823Sharti GET3BYTE(op.param.tparam.icr, addr, alen); 202118823Sharti GET3BYTE(op.param.tparam.tbe, addr, alen); 203118823Sharti GET1BYTE(op.param.tparam.nrm, addr, alen); 204118823Sharti GET1BYTE(op.param.tparam.trm, addr, alen); 205118823Sharti GET2BYTE(op.param.tparam.adtf, addr, alen); 206118823Sharti GET1BYTE(op.param.tparam.rif, addr, alen); 207118823Sharti GET1BYTE(op.param.tparam.rdf, addr, alen); 208118823Sharti GET1BYTE(op.param.tparam.cdf, addr, alen); 209118552Sharti break; 210118552Sharti 211118552Sharti default: 212118552Sharti bad_param: 213118552Sharti printf("%s: bad traffic params\n", __func__); 214118552Sharti goto failed; 215118552Sharti } 216118552Sharti } 217118552Sharti op.param.rmtu = op.param.tmtu = rt->rt_ifp->if_mtu; 21825603Skjc#ifdef NATM 21925603Skjc /* 22025603Skjc * let native ATM know we are using this VCI/VPI 22125603Skjc * (i.e. reserve it) 22225603Skjc */ 22325603Skjc sin = (struct sockaddr_in *) rt_key(rt); 22425603Skjc if (sin->sin_family != AF_INET) 22525603Skjc goto failed; 226118552Sharti npcb = npcb_add(NULL, rt->rt_ifp, op.param.vci, op.param.vpi); 227133874Srwatson if (npcb == NULL) 22825603Skjc goto failed; 22925603Skjc npcb->npcb_flags |= NPCB_IP; 23025603Skjc npcb->ipaddr.s_addr = sin->sin_addr.s_addr; 23125603Skjc /* XXX: move npcb to llinfo when ATM ARP is ready */ 232216466Sbz#ifdef __notyet_restored__ 23325603Skjc rt->rt_llinfo = (caddr_t) npcb; 234216466Sbz#endif 23525603Skjc rt->rt_flags |= RTF_LLINFO; 23625603Skjc#endif 23725603Skjc /* 23825603Skjc * let the lower level know this circuit is active 23925603Skjc */ 240118552Sharti op.rxhand = NULL; 241118552Sharti op.param.flags |= ATMIO_FLAG_ASYNC; 242133874Srwatson if (rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMOPENVCC, 243118552Sharti (caddr_t)&op) != 0) { 24425603Skjc printf("atm: couldn't add VC\n"); 24525603Skjc goto failed; 24625603Skjc } 24725603Skjc 24825603Skjc SDL(gate)->sdl_type = rt->rt_ifp->if_type; 24925603Skjc SDL(gate)->sdl_index = rt->rt_ifp->if_index; 25025603Skjc 251148980Srodrigc#ifdef NATM 252148980Srodrigc NATM_UNLOCK(); 253148980Srodrigc#endif 25425603Skjc break; 25525603Skjc 25625603Skjcfailed: 25725603Skjc#ifdef NATM 25825603Skjc if (npcb) { 25925603Skjc npcb_free(npcb, NPCB_DESTROY); 260216466Sbz#ifdef __notyet_restored__ 26125603Skjc rt->rt_llinfo = NULL; 262216466Sbz#endif 26325603Skjc rt->rt_flags &= ~RTF_LLINFO; 26425603Skjc } 265148980Srodrigc NATM_UNLOCK(); 26625603Skjc#endif 267118499Sharti /* mark as invalid. We cannot RTM_DELETE the route from 268118499Sharti * here, because the recursive call to rtrequest1 does 269118499Sharti * not really work. */ 270118499Sharti rt->rt_flags |= RTF_REJECT; 27125603Skjc break; 27225603Skjc 27325603Skjc case RTM_DELETE: 27425603Skjc#ifdef NATM 27525603Skjc /* 27625603Skjc * tell native ATM we are done with this VC 27725603Skjc */ 27825603Skjc if (rt->rt_flags & RTF_LLINFO) { 279148980Srodrigc NATM_LOCK(); 280216466Sbz#ifdef __notyet_restored__ 281133874Srwatson npcb_free((struct natmpcb *)rt->rt_llinfo, 282118497Sharti NPCB_DESTROY); 28325603Skjc rt->rt_llinfo = NULL; 284216466Sbz#endif 28525603Skjc rt->rt_flags &= ~RTF_LLINFO; 286148980Srodrigc NATM_UNLOCK(); 28725603Skjc } 28825603Skjc#endif 28925603Skjc /* 29025603Skjc * tell the lower layer to disable this circuit 29125603Skjc */ 292118552Sharti bzero(&op, sizeof(op)); 293118552Sharti addr = LLADDR(SDL(gate)); 294118552Sharti addr++; 295118552Sharti cl.vpi = *addr++; 296118552Sharti cl.vci = *addr++ << 8; 297118552Sharti cl.vci |= *addr++; 298133874Srwatson (void)rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMCLOSEVCC, 299118552Sharti (caddr_t)&cl); 30025603Skjc break; 30125603Skjc } 30225603Skjc} 30325603Skjc 30425603Skjc/* 30525603Skjc * atmresolve: 30625603Skjc * inputs: 30725603Skjc * [1] "rt" = the link level route to use (or null if need to look one up) 30825603Skjc * [2] "m" = mbuf containing the data to be sent 30925603Skjc * [3] "dst" = sockaddr_in (IP) address of dest. 31025603Skjc * output: 31125603Skjc * [4] "desten" = ATM pseudo header which we will fill in VPI/VCI info 312133874Srwatson * return: 31325603Skjc * 0 == resolve FAILED; note that "m" gets m_freem'd in this case 31425603Skjc * 1 == resolve OK; desten contains result 31525603Skjc * 31625603Skjc * XXX: will need more work if we wish to support ATMARP in the kernel, 31725603Skjc * but this is enough for PVCs entered via the "route" command. 31825603Skjc */ 31925603Skjcint 320249925Sglebiusatmresolve(struct rtentry *rt, struct mbuf *m, const struct sockaddr *dst, 321118497Sharti struct atm_pseudohdr *desten) 32225603Skjc{ 32325603Skjc struct sockaddr_dl *sdl; 32425603Skjc 325118497Sharti if (m->m_flags & (M_BCAST | M_MCAST)) { 326149506Sglebius log(LOG_INFO, 327149506Sglebius "atmresolve: BCAST/MCAST packet detected/dumped\n"); 32825603Skjc goto bad; 32925603Skjc } 33025603Skjc 33125603Skjc if (rt == NULL) { 332249925Sglebius /* link level on table 0 XXX MRT */ 333249925Sglebius rt = RTALLOC1(__DECONST(struct sockaddr *, dst), 0); 334118497Sharti if (rt == NULL) 335118497Sharti goto bad; /* failed */ 336122334Ssam RT_REMREF(rt); /* don't keep LL references */ 337133874Srwatson if ((rt->rt_flags & RTF_GATEWAY) != 0 || 338118497Sharti rt->rt_gateway->sa_family != AF_LINK) { 339120727Ssam RT_UNLOCK(rt); 340118497Sharti goto bad; 34125603Skjc } 342120727Ssam RT_UNLOCK(rt); 34325603Skjc } 34425603Skjc 34525603Skjc /* 346133874Srwatson * note that rt_gateway is a sockaddr_dl which contains the 34725603Skjc * atm_pseudohdr data structure for this route. we currently 34825603Skjc * don't need any rt_llinfo info (but will if we want to support 34925603Skjc * ATM ARP [c.f. if_ether.c]). 35025603Skjc */ 35125603Skjc sdl = SDL(rt->rt_gateway); 35225603Skjc 35325603Skjc /* 35425603Skjc * Check the address family and length is valid, the address 35525603Skjc * is resolved; otherwise, try to resolve. 35625603Skjc */ 357118552Sharti if (sdl->sdl_family == AF_LINK && sdl->sdl_alen >= sizeof(*desten)) { 358118552Sharti bcopy(LLADDR(sdl), desten, sizeof(*desten)); 359118552Sharti return (1); /* ok, go for it! */ 36025603Skjc } 36125603Skjc 36225603Skjc /* 36325603Skjc * we got an entry, but it doesn't have valid link address 36425603Skjc * info in it (it is prob. the interface route, which has 36525603Skjc * sdl_alen == 0). dump packet. (fall through to "bad"). 36625603Skjc */ 36725603Skjcbad: 36825603Skjc m_freem(m); 369118497Sharti return (0); 37025603Skjc} 37125603Skjc#endif /* INET */ 372