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> 55257176Sglebius#include <net/if_var.h> 5625603Skjc#include <net/if_dl.h> 5725603Skjc#include <net/route.h> 5825603Skjc#include <net/if_atm.h> 5925603Skjc 6025603Skjc#include <netinet/in.h> 6125603Skjc#include <netinet/if_atm.h> 6225603Skjc 6325603Skjc#ifdef NATM 6425603Skjc#include <netnatm/natm.h> 6525603Skjc#endif 6625603Skjc 6725603Skjc#define SDL(s) ((struct sockaddr_dl *)s) 6825603Skjc 69118823Sharti#define GET3BYTE(V, A, L) do { \ 70118823Sharti (V) = ((A)[0] << 16) | ((A)[1] << 8) | (A)[2]; \ 71118823Sharti (A) += 3; \ 72118823Sharti (L) -= 3; \ 73118823Sharti } while (0) 74118823Sharti 75118823Sharti#define GET2BYTE(V, A, L) do { \ 76118823Sharti (V) = ((A)[0] << 8) | (A)[1]; \ 77118823Sharti (A) += 2; \ 78118823Sharti (L) -= 2; \ 79118823Sharti } while (0) 80118823Sharti 81118823Sharti#define GET1BYTE(V, A, L) do { \ 82118823Sharti (V) = *(A)++; \ 83118823Sharti (L)--; \ 84118823Sharti } while (0) 85118823Sharti 86118823Sharti 8725603Skjc/* 8825603Skjc * atm_rtrequest: handle ATM rt request (in support of generic code) 8925603Skjc * inputs: "req" = request code 9025603Skjc * "rt" = route entry 9185074Sru * "info" = rt_addrinfo 9225603Skjc */ 9325603Skjcvoid 94118497Shartiatm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) 9525603Skjc{ 96118497Sharti struct sockaddr *gate = rt->rt_gateway; 97118552Sharti struct atmio_openvcc op; 98118552Sharti struct atmio_closevcc cl; 99118552Sharti u_char *addr; 100118552Sharti u_int alen; 10125603Skjc#ifdef NATM 10225603Skjc struct sockaddr_in *sin; 10325603Skjc struct natmpcb *npcb = NULL; 10425603Skjc#endif 10525603Skjc static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; 10625603Skjc 10725603Skjc if (rt->rt_flags & RTF_GATEWAY) /* link level requests only */ 10825603Skjc return; 10925603Skjc 11025603Skjc switch (req) { 11125603Skjc 11225603Skjc case RTM_RESOLVE: /* resolve: only happens when cloning */ 11325603Skjc printf("atm_rtrequest: RTM_RESOLVE request detected?\n"); 11425603Skjc break; 11525603Skjc 11625603Skjc case RTM_ADD: 11725603Skjc /* 11825603Skjc * route added by a command (e.g. ifconfig, route, arp...). 11925603Skjc * 12025603Skjc * first check to see if this is not a host route, in which 12125603Skjc * case we are being called via "ifconfig" to set the address. 12225603Skjc */ 123133874Srwatson if ((rt->rt_flags & RTF_HOST) == 0) { 12425603Skjc rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl); 12525603Skjc gate = rt->rt_gateway; 12625603Skjc SDL(gate)->sdl_type = rt->rt_ifp->if_type; 12725603Skjc SDL(gate)->sdl_index = rt->rt_ifp->if_index; 12825603Skjc break; 12925603Skjc } 13025603Skjc 13125603Skjc if (gate->sa_family != AF_LINK || 13225603Skjc gate->sa_len < sizeof(null_sdl)) { 13325603Skjc log(LOG_DEBUG, "atm_rtrequest: bad gateway value"); 13425603Skjc break; 13525603Skjc } 13625603Skjc 13797074Sarr KASSERT(rt->rt_ifp->if_ioctl != NULL, 13897074Sarr ("atm_rtrequest: null ioctl")); 139118552Sharti 140118552Sharti /* 141118552Sharti * Parse and verify the link level address as 142118552Sharti * an open request 143118552Sharti */ 144148980Srodrigc#ifdef NATM 145148980Srodrigc NATM_LOCK(); 146148980Srodrigc#endif 147118552Sharti bzero(&op, sizeof(op)); 148118552Sharti addr = LLADDR(SDL(gate)); 149118552Sharti alen = SDL(gate)->sdl_alen; 150118552Sharti if (alen < 4) { 151118552Sharti printf("%s: bad link-level address\n", __func__); 152118552Sharti goto failed; 153118552Sharti } 154118552Sharti 155118552Sharti if (alen == 4) { 156118552Sharti /* old type address */ 157118823Sharti GET1BYTE(op.param.flags, addr, alen); 158118823Sharti GET1BYTE(op.param.vpi, addr, alen); 159118823Sharti GET2BYTE(op.param.vci, addr, alen); 160118552Sharti op.param.traffic = ATMIO_TRAFFIC_UBR; 161118552Sharti op.param.aal = (op.param.flags & ATM_PH_AAL5) ? 162118552Sharti ATMIO_AAL_5 : ATMIO_AAL_0; 163118552Sharti } else { 164118552Sharti /* new address */ 165118552Sharti op.param.aal = ATMIO_AAL_5; 166118823Sharti 167118823Sharti GET1BYTE(op.param.flags, addr, alen); 168118823Sharti op.param.flags &= ATM_PH_LLCSNAP; 169118823Sharti 170118823Sharti GET1BYTE(op.param.vpi, addr, alen); 171118823Sharti GET2BYTE(op.param.vci, addr, alen); 172118823Sharti 173118823Sharti GET1BYTE(op.param.traffic, addr, alen); 174118823Sharti 175118552Sharti switch (op.param.traffic) { 176118552Sharti 177118552Sharti case ATMIO_TRAFFIC_UBR: 178118823Sharti if (alen >= 3) 179118823Sharti GET3BYTE(op.param.tparam.pcr, 180118823Sharti addr, alen); 181118552Sharti break; 182118552Sharti 183118552Sharti case ATMIO_TRAFFIC_CBR: 184118552Sharti if (alen < 3) 185118552Sharti goto bad_param; 186118823Sharti GET3BYTE(op.param.tparam.pcr, addr, alen); 187118552Sharti break; 188118552Sharti 189118552Sharti case ATMIO_TRAFFIC_VBR: 190118552Sharti if (alen < 3 * 3) 191118552Sharti goto bad_param; 192118823Sharti GET3BYTE(op.param.tparam.pcr, addr, alen); 193118823Sharti GET3BYTE(op.param.tparam.scr, addr, alen); 194118823Sharti GET3BYTE(op.param.tparam.mbs, addr, alen); 195118552Sharti break; 196118552Sharti 197118552Sharti case ATMIO_TRAFFIC_ABR: 198118823Sharti if (alen < 4 * 3 + 2 + 1 * 2 + 3) 199118552Sharti goto bad_param; 200118823Sharti GET3BYTE(op.param.tparam.pcr, addr, alen); 201118823Sharti GET3BYTE(op.param.tparam.mcr, addr, alen); 202118823Sharti GET3BYTE(op.param.tparam.icr, addr, alen); 203118823Sharti GET3BYTE(op.param.tparam.tbe, addr, alen); 204118823Sharti GET1BYTE(op.param.tparam.nrm, addr, alen); 205118823Sharti GET1BYTE(op.param.tparam.trm, addr, alen); 206118823Sharti GET2BYTE(op.param.tparam.adtf, addr, alen); 207118823Sharti GET1BYTE(op.param.tparam.rif, addr, alen); 208118823Sharti GET1BYTE(op.param.tparam.rdf, addr, alen); 209118823Sharti GET1BYTE(op.param.tparam.cdf, addr, alen); 210118552Sharti break; 211118552Sharti 212118552Sharti default: 213118552Sharti bad_param: 214118552Sharti printf("%s: bad traffic params\n", __func__); 215118552Sharti goto failed; 216118552Sharti } 217118552Sharti } 218118552Sharti op.param.rmtu = op.param.tmtu = rt->rt_ifp->if_mtu; 21925603Skjc#ifdef NATM 22025603Skjc /* 22125603Skjc * let native ATM know we are using this VCI/VPI 22225603Skjc * (i.e. reserve it) 22325603Skjc */ 22425603Skjc sin = (struct sockaddr_in *) rt_key(rt); 22525603Skjc if (sin->sin_family != AF_INET) 22625603Skjc goto failed; 227118552Sharti npcb = npcb_add(NULL, rt->rt_ifp, op.param.vci, op.param.vpi); 228133874Srwatson if (npcb == NULL) 22925603Skjc goto failed; 23025603Skjc npcb->npcb_flags |= NPCB_IP; 23125603Skjc npcb->ipaddr.s_addr = sin->sin_addr.s_addr; 23225603Skjc /* XXX: move npcb to llinfo when ATM ARP is ready */ 233216466Sbz#ifdef __notyet_restored__ 23425603Skjc rt->rt_llinfo = (caddr_t) npcb; 235216466Sbz#endif 23625603Skjc rt->rt_flags |= RTF_LLINFO; 23725603Skjc#endif 23825603Skjc /* 23925603Skjc * let the lower level know this circuit is active 24025603Skjc */ 241118552Sharti op.rxhand = NULL; 242118552Sharti op.param.flags |= ATMIO_FLAG_ASYNC; 243133874Srwatson if (rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMOPENVCC, 244118552Sharti (caddr_t)&op) != 0) { 24525603Skjc printf("atm: couldn't add VC\n"); 24625603Skjc goto failed; 24725603Skjc } 24825603Skjc 24925603Skjc SDL(gate)->sdl_type = rt->rt_ifp->if_type; 25025603Skjc SDL(gate)->sdl_index = rt->rt_ifp->if_index; 25125603Skjc 252148980Srodrigc#ifdef NATM 253148980Srodrigc NATM_UNLOCK(); 254148980Srodrigc#endif 25525603Skjc break; 25625603Skjc 25725603Skjcfailed: 25825603Skjc#ifdef NATM 25925603Skjc if (npcb) { 26025603Skjc npcb_free(npcb, NPCB_DESTROY); 261216466Sbz#ifdef __notyet_restored__ 26225603Skjc rt->rt_llinfo = NULL; 263216466Sbz#endif 26425603Skjc rt->rt_flags &= ~RTF_LLINFO; 26525603Skjc } 266148980Srodrigc NATM_UNLOCK(); 26725603Skjc#endif 268118499Sharti /* mark as invalid. We cannot RTM_DELETE the route from 269118499Sharti * here, because the recursive call to rtrequest1 does 270118499Sharti * not really work. */ 271118499Sharti rt->rt_flags |= RTF_REJECT; 27225603Skjc break; 27325603Skjc 27425603Skjc case RTM_DELETE: 27525603Skjc#ifdef NATM 27625603Skjc /* 27725603Skjc * tell native ATM we are done with this VC 27825603Skjc */ 27925603Skjc if (rt->rt_flags & RTF_LLINFO) { 280148980Srodrigc NATM_LOCK(); 281216466Sbz#ifdef __notyet_restored__ 282133874Srwatson npcb_free((struct natmpcb *)rt->rt_llinfo, 283118497Sharti NPCB_DESTROY); 28425603Skjc rt->rt_llinfo = NULL; 285216466Sbz#endif 28625603Skjc rt->rt_flags &= ~RTF_LLINFO; 287148980Srodrigc NATM_UNLOCK(); 28825603Skjc } 28925603Skjc#endif 29025603Skjc /* 29125603Skjc * tell the lower layer to disable this circuit 29225603Skjc */ 293118552Sharti bzero(&op, sizeof(op)); 294118552Sharti addr = LLADDR(SDL(gate)); 295118552Sharti addr++; 296118552Sharti cl.vpi = *addr++; 297118552Sharti cl.vci = *addr++ << 8; 298118552Sharti cl.vci |= *addr++; 299133874Srwatson (void)rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMCLOSEVCC, 300118552Sharti (caddr_t)&cl); 30125603Skjc break; 30225603Skjc } 30325603Skjc} 30425603Skjc 30525603Skjc/* 30625603Skjc * atmresolve: 30725603Skjc * inputs: 30825603Skjc * [1] "rt" = the link level route to use (or null if need to look one up) 30925603Skjc * [2] "m" = mbuf containing the data to be sent 31025603Skjc * [3] "dst" = sockaddr_in (IP) address of dest. 31125603Skjc * output: 31225603Skjc * [4] "desten" = ATM pseudo header which we will fill in VPI/VCI info 313133874Srwatson * return: 31425603Skjc * 0 == resolve FAILED; note that "m" gets m_freem'd in this case 31525603Skjc * 1 == resolve OK; desten contains result 31625603Skjc * 31725603Skjc * XXX: will need more work if we wish to support ATMARP in the kernel, 31825603Skjc * but this is enough for PVCs entered via the "route" command. 31925603Skjc */ 32025603Skjcint 321249925Sglebiusatmresolve(struct rtentry *rt, struct mbuf *m, const struct sockaddr *dst, 322118497Sharti struct atm_pseudohdr *desten) 32325603Skjc{ 32425603Skjc struct sockaddr_dl *sdl; 32525603Skjc 326118497Sharti if (m->m_flags & (M_BCAST | M_MCAST)) { 327149506Sglebius log(LOG_INFO, 328149506Sglebius "atmresolve: BCAST/MCAST packet detected/dumped\n"); 32925603Skjc goto bad; 33025603Skjc } 33125603Skjc 33225603Skjc if (rt == NULL) { 333249925Sglebius /* link level on table 0 XXX MRT */ 334249925Sglebius rt = RTALLOC1(__DECONST(struct sockaddr *, dst), 0); 335118497Sharti if (rt == NULL) 336118497Sharti goto bad; /* failed */ 337122334Ssam RT_REMREF(rt); /* don't keep LL references */ 338133874Srwatson if ((rt->rt_flags & RTF_GATEWAY) != 0 || 339118497Sharti rt->rt_gateway->sa_family != AF_LINK) { 340120727Ssam RT_UNLOCK(rt); 341118497Sharti goto bad; 34225603Skjc } 343120727Ssam RT_UNLOCK(rt); 34425603Skjc } 34525603Skjc 34625603Skjc /* 347133874Srwatson * note that rt_gateway is a sockaddr_dl which contains the 34825603Skjc * atm_pseudohdr data structure for this route. we currently 34925603Skjc * don't need any rt_llinfo info (but will if we want to support 35025603Skjc * ATM ARP [c.f. if_ether.c]). 35125603Skjc */ 35225603Skjc sdl = SDL(rt->rt_gateway); 35325603Skjc 35425603Skjc /* 35525603Skjc * Check the address family and length is valid, the address 35625603Skjc * is resolved; otherwise, try to resolve. 35725603Skjc */ 358118552Sharti if (sdl->sdl_family == AF_LINK && sdl->sdl_alen >= sizeof(*desten)) { 359118552Sharti bcopy(LLADDR(sdl), desten, sizeof(*desten)); 360118552Sharti return (1); /* ok, go for it! */ 36125603Skjc } 36225603Skjc 36325603Skjc /* 36425603Skjc * we got an entry, but it doesn't have valid link address 36525603Skjc * info in it (it is prob. the interface route, which has 36625603Skjc * sdl_alen == 0). dump packet. (fall through to "bad"). 36725603Skjc */ 36825603Skjcbad: 36925603Skjc m_freem(m); 370118497Sharti return (0); 37125603Skjc} 37225603Skjc#endif /* INET */ 373