1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* $NetBSD: if_atm.c,v 1.6 1996/10/13 02:03:01 christos Exp $ */ 29 30/* 31 * 32 * Copyright (c) 1996 Charles D. Cranor and Washington University. 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. All advertising materials mentioning features or use of this software 44 * must display the following acknowledgement: 45 * This product includes software developed by Charles D. Cranor and 46 * Washington University. 47 * 4. The name of the author may not be used to endorse or promote products 48 * derived from this software without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * 61 * $FreeBSD: src/sys/netinet/if_atm.c,v 1.8 1999/12/07 17:39:06 shin Exp $ 62 */ 63 64/* 65 * IP <=> ATM address resolution. 66 */ 67 68#if defined(INET) || defined(INET6) 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/queue.h> 73#include <sys/mbuf.h> 74#include <sys/socket.h> 75#include <sys/sockio.h> 76#include <sys/syslog.h> 77 78#include <net/if.h> 79#include <net/if_dl.h> 80#include <net/route.h> 81#include <net/if_atm.h> 82 83#include <netinet/in.h> 84#include <netinet/if_atm.h> 85#include <net/dlil.h> 86 87 88#if NATM 89#include <netnatm/natm.h> 90#endif 91 92 93#define SDL(s) ((struct sockaddr_dl *)s) 94 95/* 96 * atm_rtrequest: handle ATM rt request (in support of generic code) 97 * inputs: "req" = request code 98 * "rt" = route entry 99 * "sa" = sockaddr 100 */ 101 102void 103atm_rtrequest(req, rt, sa) 104 int req; 105 register struct rtentry *rt; 106 struct sockaddr *sa; 107{ 108 register struct sockaddr *gate = rt->rt_gateway; 109 struct atm_pseudoioctl api; 110#if NATM 111 struct sockaddr_in *sin; 112 struct natmpcb *npcb = NULL; 113 struct atm_pseudohdr *aph; 114#endif 115 static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; 116 117 if (rt->rt_flags & RTF_GATEWAY) /* link level requests only */ 118 return; 119 120 switch (req) { 121 122 case RTM_RESOLVE: /* resolve: only happens when cloning */ 123 printf("atm_rtrequest: RTM_RESOLVE request detected?\n"); 124 break; 125 126 case RTM_ADD: 127 128 /* 129 * route added by a command (e.g. ifconfig, route, arp...). 130 * 131 * first check to see if this is not a host route, in which 132 * case we are being called via "ifconfig" to set the address. 133 */ 134 135 if ((rt->rt_flags & RTF_HOST) == 0) { 136 rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl); 137 gate = rt->rt_gateway; 138 SDL(gate)->sdl_type = rt->rt_ifp->if_type; 139 SDL(gate)->sdl_index = rt->rt_ifp->if_index; 140 break; 141 } 142 143 if ((rt->rt_flags & RTF_CLONING) != 0) { 144 printf("atm_rtrequest: cloning route detected?\n"); 145 break; 146 } 147 if (gate->sa_family != AF_LINK || 148 gate->sa_len < sizeof(null_sdl)) { 149 log(LOG_DEBUG, "atm_rtrequest: bad gateway value"); 150 break; 151 } 152 153#if DIAGNOSTIC 154 if (rt->rt_ifp->if_ioctl == NULL) panic("atm null ioctl"); 155#endif 156 157#if NATM 158 /* 159 * let native ATM know we are using this VCI/VPI 160 * (i.e. reserve it) 161 */ 162 sin = (struct sockaddr_in *) rt_key(rt); 163 if (sin->sin_family != AF_INET) 164 goto failed; 165 aph = (struct atm_pseudohdr *) LLADDR(SDL(gate)); 166 npcb = npcb_add(NULL, rt->rt_ifp, ATM_PH_VCI(aph), 167 ATM_PH_VPI(aph)); 168 if (npcb == NULL) 169 goto failed; 170 npcb->npcb_flags |= NPCB_IP; 171 npcb->ipaddr.s_addr = sin->sin_addr.s_addr; 172 /* XXX: move npcb to llinfo when ATM ARP is ready */ 173 rt->rt_llinfo = (caddr_t) npcb; 174 rt->rt_flags |= RTF_LLINFO; 175#endif 176 /* 177 * let the lower level know this circuit is active 178 */ 179 bcopy(LLADDR(SDL(gate)), &api.aph, sizeof(api.aph)); 180 api.rxhand = NULL; 181 if (ifnet_ioctl(rt->rt_ifpm 0, SIOCATMENA, &api) != 0) { 182 printf("atm: couldn't add VC\n"); 183 goto failed; 184 } 185 186 SDL(gate)->sdl_type = rt->rt_ifp->if_type; 187 SDL(gate)->sdl_index = rt->rt_ifp->if_index; 188 189 break; 190 191failed: 192#if NATM 193 if (npcb) { 194 npcb_free(npcb, NPCB_DESTROY); 195 rt->rt_llinfo = NULL; 196 rt->rt_flags &= ~RTF_LLINFO; 197 } 198#endif 199 rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, 200 rt_mask(rt), 0, (struct rtentry **) 0); 201 break; 202 203 case RTM_DELETE: 204 205#if NATM 206 /* 207 * tell native ATM we are done with this VC 208 */ 209 210 if (rt->rt_flags & RTF_LLINFO) { 211 npcb_free((struct natmpcb *)rt->rt_llinfo, 212 NPCB_DESTROY); 213 rt->rt_llinfo = NULL; 214 rt->rt_flags &= ~RTF_LLINFO; 215 } 216#endif 217 /* 218 * tell the lower layer to disable this circuit 219 */ 220 221 bcopy(LLADDR(SDL(gate)), &api.aph, sizeof(api.aph)); 222 api.rxhand = NULL; 223 ifnet_ioctl(rt->rt_ifp, 0, SIOCATMDIS, &api); 224 225 break; 226 } 227} 228 229/* 230 * atmresolve: 231 * inputs: 232 * [1] "rt" = the link level route to use (or null if need to look one up) 233 * [2] "m" = mbuf containing the data to be sent 234 * [3] "dst" = sockaddr_in (IP) address of dest. 235 * output: 236 * [4] "desten" = ATM pseudo header which we will fill in VPI/VCI info 237 * return: 238 * 0 == resolve FAILED; note that "m" gets m_freem'd in this case 239 * 1 == resolve OK; desten contains result 240 * 241 * XXX: will need more work if we wish to support ATMARP in the kernel, 242 * but this is enough for PVCs entered via the "route" command. 243 */ 244 245int 246atmresolve(rt, m, dst, desten) 247 248register struct rtentry *rt; 249struct mbuf *m; 250register struct sockaddr *dst; 251register struct atm_pseudohdr *desten; /* OUT */ 252 253{ 254 struct sockaddr_dl *sdl; 255 256 if (m->m_flags & (M_BCAST|M_MCAST)) { 257 log(LOG_INFO, "atmresolve: BCAST/MCAST packet detected/dumped"); 258 goto bad; 259 } 260 261 if (rt == NULL) { 262 rt = RTALLOC1(dst, 0); 263 if (rt == NULL) goto bad; /* failed */ 264 rtunref(rt); /* don't keep LL references */ 265 if ((rt->rt_flags & RTF_GATEWAY) != 0 || 266 (rt->rt_flags & RTF_LLINFO) == 0 || 267 /* XXX: are we using LLINFO? */ 268 rt->rt_gateway->sa_family != AF_LINK) { 269 goto bad; 270 } 271 } 272 273 /* 274 * note that rt_gateway is a sockaddr_dl which contains the 275 * atm_pseudohdr data structure for this route. we currently 276 * don't need any rt_llinfo info (but will if we want to support 277 * ATM ARP [c.f. if_ether.c]). 278 */ 279 280 sdl = SDL(rt->rt_gateway); 281 282 /* 283 * Check the address family and length is valid, the address 284 * is resolved; otherwise, try to resolve. 285 */ 286 287 288 if (sdl->sdl_family == AF_LINK && sdl->sdl_alen == sizeof(*desten)) { 289 bcopy(LLADDR(sdl), desten, sdl->sdl_alen); 290 return(1); /* ok, go for it! */ 291 } 292 293 /* 294 * we got an entry, but it doesn't have valid link address 295 * info in it (it is prob. the interface route, which has 296 * sdl_alen == 0). dump packet. (fall through to "bad"). 297 */ 298 299bad: 300 m_freem(m); 301 return(0); 302} 303#endif /* INET */ 304