if_atm.c revision 118552
1/* $NetBSD: if_atm.c,v 1.6 1996/10/13 02:03:01 christos Exp $ */ 2 3/* 4 * 5 * Copyright (c) 1996 Charles D. Cranor and Washington University. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Charles D. Cranor and 19 * Washington University. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: head/sys/netinet/if_atm.c 118552 2003-08-06 15:56:37Z harti $"); 36 37/* 38 * IP <=> ATM address resolution. 39 */ 40#include "opt_inet.h" 41#include "opt_inet6.h" 42#include "opt_natm.h" 43 44#if defined(INET) || defined(INET6) 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/queue.h> 49#include <sys/mbuf.h> 50#include <sys/socket.h> 51#include <sys/sockio.h> 52#include <sys/syslog.h> 53 54#include <net/if.h> 55#include <net/if_dl.h> 56#include <net/route.h> 57#include <net/if_atm.h> 58 59#include <netinet/in.h> 60#include <netinet/if_atm.h> 61 62#ifdef NATM 63#include <netnatm/natm.h> 64#endif 65 66#define SDL(s) ((struct sockaddr_dl *)s) 67 68/* 69 * atm_rtrequest: handle ATM rt request (in support of generic code) 70 * inputs: "req" = request code 71 * "rt" = route entry 72 * "info" = rt_addrinfo 73 */ 74void 75atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) 76{ 77 struct sockaddr *gate = rt->rt_gateway; 78 struct atmio_openvcc op; 79 struct atmio_closevcc cl; 80 u_char *addr; 81 u_int alen; 82#ifdef NATM 83 struct sockaddr_in *sin; 84 struct natmpcb *npcb = NULL; 85#endif 86 static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; 87 88 if (rt->rt_flags & RTF_GATEWAY) /* link level requests only */ 89 return; 90 91 switch (req) { 92 93 case RTM_RESOLVE: /* resolve: only happens when cloning */ 94 printf("atm_rtrequest: RTM_RESOLVE request detected?\n"); 95 break; 96 97 case RTM_ADD: 98 /* 99 * route added by a command (e.g. ifconfig, route, arp...). 100 * 101 * first check to see if this is not a host route, in which 102 * case we are being called via "ifconfig" to set the address. 103 */ 104 if ((rt->rt_flags & RTF_HOST) == 0) { 105 rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl); 106 gate = rt->rt_gateway; 107 SDL(gate)->sdl_type = rt->rt_ifp->if_type; 108 SDL(gate)->sdl_index = rt->rt_ifp->if_index; 109 break; 110 } 111 112 if ((rt->rt_flags & RTF_CLONING) != 0) { 113 printf("atm_rtrequest: cloning route detected?\n"); 114 break; 115 } 116 if (gate->sa_family != AF_LINK || 117 gate->sa_len < sizeof(null_sdl)) { 118 log(LOG_DEBUG, "atm_rtrequest: bad gateway value"); 119 break; 120 } 121 122 KASSERT(rt->rt_ifp->if_ioctl != NULL, 123 ("atm_rtrequest: null ioctl")); 124 125 /* 126 * Parse and verify the link level address as 127 * an open request 128 */ 129 bzero(&op, sizeof(op)); 130 addr = LLADDR(SDL(gate)); 131 alen = SDL(gate)->sdl_alen; 132 if (alen < 4) { 133 printf("%s: bad link-level address\n", __func__); 134 goto failed; 135 } 136 137 if (alen == 4) { 138 /* old type address */ 139 op.param.flags = *addr++; 140 op.param.vpi = *addr++; 141 op.param.vci = *addr++ << 8; 142 op.param.vci |= *addr++; 143 op.param.traffic = ATMIO_TRAFFIC_UBR; 144 op.param.aal = (op.param.flags & ATM_PH_AAL5) ? 145 ATMIO_AAL_5 : ATMIO_AAL_0; 146 } else { 147 /* new address */ 148 op.param.aal = ATMIO_AAL_5; 149 /* 1. byte LLC/SNAP flag */ 150 op.param.flags = *addr++ & ATM_PH_LLCSNAP; 151 alen--; 152 /* 2.-4. byte VPI/VCI */ 153 op.param.vpi = *addr++; 154 op.param.vci = *addr++ << 8; 155 op.param.vci |= *addr++; 156 alen -= 3; 157 /* 5. byte: traffic */ 158 op.param.traffic = *addr++; 159 alen--; 160 switch (op.param.traffic) { 161 162 case ATMIO_TRAFFIC_UBR: 163 if (alen >= 3) { 164 op.param.tparam.pcr = *addr++ << 16; 165 op.param.tparam.pcr = *addr++ << 8; 166 op.param.tparam.pcr = *addr++ << 0; 167 alen -= 3; 168 } 169 break; 170 171 case ATMIO_TRAFFIC_CBR: 172 if (alen < 3) 173 goto bad_param; 174 op.param.tparam.pcr = *addr++ << 16; 175 op.param.tparam.pcr = *addr++ << 8; 176 op.param.tparam.pcr = *addr++ << 0; 177 alen -= 3; 178 break; 179 180 case ATMIO_TRAFFIC_VBR: 181 if (alen < 3 * 3) 182 goto bad_param; 183 op.param.tparam.pcr = *addr++ << 16; 184 op.param.tparam.pcr = *addr++ << 8; 185 op.param.tparam.pcr = *addr++ << 0; 186 alen -= 3; 187 op.param.tparam.scr = *addr++ << 16; 188 op.param.tparam.scr = *addr++ << 8; 189 op.param.tparam.scr = *addr++ << 0; 190 alen -= 3; 191 op.param.tparam.mbs = *addr++ << 16; 192 op.param.tparam.mbs = *addr++ << 8; 193 op.param.tparam.mbs = *addr++ << 0; 194 alen -= 3; 195 break; 196 197 case ATMIO_TRAFFIC_ABR: 198 if (alen < 4 * 3 + 1 * 2 + 5 + 1) 199 goto bad_param; 200 op.param.tparam.pcr = *addr++ << 16; 201 op.param.tparam.pcr = *addr++ << 8; 202 op.param.tparam.pcr = *addr++ << 0; 203 alen -= 3; 204 op.param.tparam.mcr = *addr++ << 16; 205 op.param.tparam.mcr = *addr++ << 8; 206 op.param.tparam.mcr = *addr++ << 0; 207 alen -= 3; 208 op.param.tparam.icr = *addr++ << 16; 209 op.param.tparam.icr = *addr++ << 8; 210 op.param.tparam.icr = *addr++ << 0; 211 alen -= 3; 212 op.param.tparam.tbe = *addr++ << 16; 213 op.param.tparam.tbe = *addr++ << 8; 214 op.param.tparam.tbe = *addr++ << 0; 215 alen -= 3; 216 op.param.tparam.nrm = *addr++; 217 alen--; 218 op.param.tparam.trm = *addr++; 219 alen--; 220 op.param.tparam.adtf = *addr++ << 8; 221 op.param.tparam.adtf = *addr++ << 0; 222 alen -= 2; 223 op.param.tparam.rif = *addr++; 224 alen--; 225 op.param.tparam.rdf = *addr++; 226 alen--; 227 op.param.tparam.cdf = *addr++; 228 alen--; 229 break; 230 231 default: 232 bad_param: 233 printf("%s: bad traffic params\n", __func__); 234 goto failed; 235 } 236 } 237 op.param.rmtu = op.param.tmtu = rt->rt_ifp->if_mtu; 238#ifdef NATM 239 /* 240 * let native ATM know we are using this VCI/VPI 241 * (i.e. reserve it) 242 */ 243 sin = (struct sockaddr_in *) rt_key(rt); 244 if (sin->sin_family != AF_INET) 245 goto failed; 246 npcb = npcb_add(NULL, rt->rt_ifp, op.param.vci, op.param.vpi); 247 if (npcb == NULL) 248 goto failed; 249 npcb->npcb_flags |= NPCB_IP; 250 npcb->ipaddr.s_addr = sin->sin_addr.s_addr; 251 /* XXX: move npcb to llinfo when ATM ARP is ready */ 252 rt->rt_llinfo = (caddr_t) npcb; 253 rt->rt_flags |= RTF_LLINFO; 254#endif 255 /* 256 * let the lower level know this circuit is active 257 */ 258 op.rxhand = NULL; 259 op.param.flags |= ATMIO_FLAG_ASYNC; 260 if (rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMOPENVCC, 261 (caddr_t)&op) != 0) { 262 printf("atm: couldn't add VC\n"); 263 goto failed; 264 } 265 266 SDL(gate)->sdl_type = rt->rt_ifp->if_type; 267 SDL(gate)->sdl_index = rt->rt_ifp->if_index; 268 269 break; 270 271failed: 272#ifdef NATM 273 if (npcb) { 274 npcb_free(npcb, NPCB_DESTROY); 275 rt->rt_llinfo = NULL; 276 rt->rt_flags &= ~RTF_LLINFO; 277 } 278#endif 279 /* mark as invalid. We cannot RTM_DELETE the route from 280 * here, because the recursive call to rtrequest1 does 281 * not really work. */ 282 rt->rt_flags |= RTF_REJECT; 283 break; 284 285 case RTM_DELETE: 286#ifdef NATM 287 /* 288 * tell native ATM we are done with this VC 289 */ 290 if (rt->rt_flags & RTF_LLINFO) { 291 npcb_free((struct natmpcb *)rt->rt_llinfo, 292 NPCB_DESTROY); 293 rt->rt_llinfo = NULL; 294 rt->rt_flags &= ~RTF_LLINFO; 295 } 296#endif 297 /* 298 * tell the lower layer to disable this circuit 299 */ 300 bzero(&op, sizeof(op)); 301 addr = LLADDR(SDL(gate)); 302 addr++; 303 cl.vpi = *addr++; 304 cl.vci = *addr++ << 8; 305 cl.vci |= *addr++; 306 (void)rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMCLOSEVCC, 307 (caddr_t)&cl); 308 break; 309 } 310} 311 312/* 313 * atmresolve: 314 * inputs: 315 * [1] "rt" = the link level route to use (or null if need to look one up) 316 * [2] "m" = mbuf containing the data to be sent 317 * [3] "dst" = sockaddr_in (IP) address of dest. 318 * output: 319 * [4] "desten" = ATM pseudo header which we will fill in VPI/VCI info 320 * return: 321 * 0 == resolve FAILED; note that "m" gets m_freem'd in this case 322 * 1 == resolve OK; desten contains result 323 * 324 * XXX: will need more work if we wish to support ATMARP in the kernel, 325 * but this is enough for PVCs entered via the "route" command. 326 */ 327int 328atmresolve(struct rtentry *rt, struct mbuf *m, struct sockaddr *dst, 329 struct atm_pseudohdr *desten) 330{ 331 struct sockaddr_dl *sdl; 332 333 if (m->m_flags & (M_BCAST | M_MCAST)) { 334 log(LOG_INFO, "atmresolve: BCAST/MCAST packet detected/dumped"); 335 goto bad; 336 } 337 338 if (rt == NULL) { 339 rt = RTALLOC1(dst, 0); 340 if (rt == NULL) 341 goto bad; /* failed */ 342 rt->rt_refcnt--; /* don't keep LL references */ 343 if ((rt->rt_flags & RTF_GATEWAY) != 0 || 344 (rt->rt_flags & RTF_LLINFO) == 0 || 345 /* XXX: are we using LLINFO? */ 346 rt->rt_gateway->sa_family != AF_LINK) { 347 goto bad; 348 } 349 } 350 351 /* 352 * note that rt_gateway is a sockaddr_dl which contains the 353 * atm_pseudohdr data structure for this route. we currently 354 * don't need any rt_llinfo info (but will if we want to support 355 * ATM ARP [c.f. if_ether.c]). 356 */ 357 sdl = SDL(rt->rt_gateway); 358 359 /* 360 * Check the address family and length is valid, the address 361 * is resolved; otherwise, try to resolve. 362 */ 363 if (sdl->sdl_family == AF_LINK && sdl->sdl_alen >= sizeof(*desten)) { 364 bcopy(LLADDR(sdl), desten, sizeof(*desten)); 365 return (1); /* ok, go for it! */ 366 } 367 368 /* 369 * we got an entry, but it doesn't have valid link address 370 * info in it (it is prob. the interface route, which has 371 * sdl_alen == 0). dump packet. (fall through to "bad"). 372 */ 373bad: 374 m_freem(m); 375 return (0); 376} 377#endif /* INET */ 378