1/* $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck 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
35/*
36 * if_atmsubr.c
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/mbuf.h>
42#include <sys/socket.h>
43
44#include <net/if.h>
45#include <net/netisr.h>
46#include <net/route.h>
47#include <net/if_dl.h>
48#include <net/if_types.h>
49#include <net/if_atm.h>
50
51#include <netinet/in.h>
52#include <netinet/if_atm.h>
53#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
54#ifdef INET
55#include <netinet/in_var.h>
56#endif
57#ifdef NATM
58#include <netnatm/natm.h>
59#endif
60
61#include "bpfilter.h"
62#if NBPFILTER > 0
63/*
64 * bpf support.
65 * the code is derived from if_loop.c.
66 * bpf support should belong to the driver but it's easier to implement
67 * it here since we can call bpf_mtap before atm_output adds a pseudo
68 * header to the mbuf.
69 * --kjc
70 */
71#include <net/bpf.h>
72#endif /* NBPFILTER > 0 */
73
74#define senderr(e) { error = (e); goto bad;}
75
76/*
77 * atm_output: ATM output routine
78 * inputs:
79 * "ifp" = ATM interface to output to
80 * "m0" = the packet to output
81 * "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
82 * "rt0" = the route to use
83 * returns: error code [0 == ok]
84 *
85 * note: special semantic: if (dst == NULL) then we assume "m" already
86 * has an atm_pseudohdr on it and just send it directly.
87 * [for native mode ATM output] if dst is null, then
88 * rt0 must also be NULL.
89 */
90
91int
92atm_output(ifp, m0, dst, rt0)
93 register struct ifnet *ifp;
94 struct mbuf *m0;
95 struct sockaddr *dst;
96 struct rtentry *rt0;
97{
98 u_int16_t etype = 0; /* if using LLC/SNAP */
99 int s, error = 0, sz;
100 struct atm_pseudohdr atmdst, *ad;
101 register struct mbuf *m = m0;
102 register struct rtentry *rt;
103 struct atmllc *atmllc;
104 u_int32_t atm_flags;
105
106 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
107 senderr(ENETDOWN);
108 gettime(&ifp->if_lastchange);
109
110 /*
111 * check route
112 */
113 if ((rt = rt0) != NULL) {
114
115 if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */
116 if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL)
117 rt->rt_refcnt--;
118 else
119 senderr(EHOSTUNREACH);
120 }
121
122 if (rt->rt_flags & RTF_GATEWAY) {
123 if (rt->rt_gwroute == 0)
124 goto lookup;
125 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
126 rtfree(rt); rt = rt0;
127 lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0);
128 if ((rt = rt->rt_gwroute) == 0)
129 senderr(EHOSTUNREACH);
130 }
131 }
132
133 /* XXX: put RTF_REJECT code here if doing ATMARP */
134
135 }
136
137 /*
138 * check for non-native ATM traffic (dst != NULL)
139 */
140 if (dst) {
141 switch (dst->sa_family) {
142#ifdef INET
143 case AF_INET:
144 if (!atmresolve(rt, m, dst, &atmdst)) {
145 m = NULL;
146 /* XXX: atmresolve already free'd it */
147 senderr(EHOSTUNREACH);
148 /* XXX: put ATMARP stuff here */
149 /* XXX: watch who frees m on failure */
150 }
151 etype = htons(ETHERTYPE_IP);
152 break;
153#endif
154
155 default:
156#if defined(__NetBSD__) || defined(__OpenBSD__)
157 printf("%s: can't handle af%d\n", ifp->if_xname,
158 dst->sa_family);
159#elif defined(__FreeBSD__) || defined(__bsdi__)
160 printf("%s%d: can't handle af%d\n", ifp->if_name,
161 ifp->if_unit, dst->sa_family);
162#endif
163 senderr(EAFNOSUPPORT);
164 }
165
166#if NBPFILTER > 0
167 /* BPF write needs to be handled specially */
168 if (dst && dst->sa_family == AF_UNSPEC) {
169 dst->sa_family = *(mtod(m, int *));
170 m->m_len -= sizeof(int);
171 m->m_pkthdr.len -= sizeof(int);
172 m->m_data += sizeof(int);
173 }
174
175 if (ifp->if_bpf) {
176 /*
177 * We need to prepend the address family as
178 * a four byte field. Cons up a dummy header
179 * to pacify bpf. This is safe because bpf
180 * will only read from the mbuf (i.e., it won't
181 * try to free it or keep a pointer a to it).
182 */
183 struct mbuf m1;
184 u_int af = dst->sa_family;
185
186 m1.m_next = m;
187 m1.m_len = 4;
188 m1.m_data = (char *)⁡
189
190 s = splimp();
191#if defined(__NetBSD__) || defined(__OpenBSD__)
192 bpf_mtap(&ifp->if_bpf, &m0);
193#elif defined(__FreeBSD__)
194 bpf_mtap(ifp, &m1);
195#endif
196 splx(s);
197 }
198#endif /* NBPFILTER > 0 */
199
200 /*
201 * must add atm_pseudohdr to data
202 */
203 sz = sizeof(atmdst);
204 atm_flags = ATM_PH_FLAGS(&atmdst);
205 if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */
206 M_PREPEND(m, sz, M_DONTWAIT);
207 if (m == 0)
208 senderr(ENOBUFS);
209 ad = mtod(m, struct atm_pseudohdr *);
210 *ad = atmdst;
211 if (atm_flags & ATM_PH_LLCSNAP) {
212 atmllc = (struct atmllc *)(ad + 1);
213 bcopy(ATMLLC_HDR, atmllc->llchdr,
214 sizeof(atmllc->llchdr));
215 ATM_LLC_SETTYPE(atmllc, etype);
216 /* note: already in network order */
217 }
218 }
219
220 /*
221 * Queue message on interface, and start output if interface
222 * not yet active.
223 */
224
225 s = splimp();
226 if (IF_QFULL(&ifp->if_snd)) {
227 IF_DROP(&ifp->if_snd);
228 splx(s);
229 senderr(ENOBUFS);
230 }
231 ifp->if_obytes += m->m_pkthdr.len;
232 IF_ENQUEUE(&ifp->if_snd, m);
233 if ((ifp->if_flags & IFF_OACTIVE) == 0)
234 (*ifp->if_start)(ifp);
235 splx(s);
236 return (error);
237
238bad:
239 if (m)
240 m_freem(m);
241 return (error);
242}
243
244/*
245 * Process a received ATM packet;
246 * the packet is in the mbuf chain m.
247 */
248void
249atm_input(ifp, ah, m, rxhand)
250 struct ifnet *ifp;
251 register struct atm_pseudohdr *ah;
252 struct mbuf *m;
253 void *rxhand;
254{
255 register struct ifqueue *inq;
256 u_int16_t etype = ETHERTYPE_IP; /* default */
257 int s;
258
259 if ((ifp->if_flags & IFF_UP) == 0) {
260 m_freem(m);
261 return;
262 }
263 gettime(&ifp->if_lastchange);
264 ifp->if_ibytes += m->m_pkthdr.len;
265
266#if NBPFILTER > 0
267 if (ifp->if_bpf) {
268 /*
269 * We need to prepend the address family as
270 * a four byte field. Cons up a dummy header
271 * to pacify bpf. This is safe because bpf
272 * will only read from the mbuf (i.e., it won't
273 * try to free it or keep a pointer to it).
274 */
275 struct mbuf m0;
276 u_int af = AF_INET;
277
278 m0.m_next = m;
279 m0.m_len = 4;
280 m0.m_data = (char *)⁡
281
282#if defined(__NetBSD__) || defined(__OpenBSD__)
283 bpf_mtap(&ifp->if_bpf, &m0);
284#elif defined(__FreeBSD__)
285 bpf_mtap(ifp, &m0);
286#endif
287 }
288#endif /* NBPFILTER > 0 */
289
290 if (rxhand) {
291#ifdef NATM
292 struct natmpcb *npcb = rxhand;
293 s = splimp(); /* in case 2 atm cards @ diff lvls */
294 npcb->npcb_inq++; /* count # in queue */
295 splx(s);
296 schednetisr(NETISR_NATM);
297 inq = &natmintrq;
298 m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
299#else
300 printf("atm_input: NATM detected but not configured in kernel\n");
301 m_freem(m);
302 return;
303#endif
304 } else {
305 /*
306 * handle LLC/SNAP header, if present
307 */
308 if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
309 struct atmllc *alc;
310 if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0)
311 return; /* failed */
312 alc = mtod(m, struct atmllc *);
313 if (bcmp(alc, ATMLLC_HDR, 6)) {
314#if defined(__NetBSD__) || defined(__OpenBSD__)
315 printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
316 ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
317#elif defined(__FreeBSD__) || defined(__bsdi__)
318 printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
319 ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
320#endif
321 m_freem(m);
322 return;
323 }
324 etype = ATM_LLC_TYPE(alc);
325 m_adj(m, sizeof(*alc));
326 }
327
328 switch (etype) {
329#ifdef INET
330 case ETHERTYPE_IP:
331 schednetisr(NETISR_IP);
332 inq = &ipintrq;
333 break;
334#endif
335 default:
336 m_freem(m);
337 return;
338 }
339 }
340
341 s = splimp();
342 if (IF_QFULL(inq)) {
343 IF_DROP(inq);
344 m_freem(m);
345 } else
346 IF_ENQUEUE(inq, m);
347 splx(s);
348}
349
350/*
351 * Perform common duties while attaching to interface list
352 */
353void
354atm_ifattach(ifp)
355 register struct ifnet *ifp;
356{
357 register struct ifaddr *ifa;
358 register struct sockaddr_dl *sdl;
359
360 ifp->if_type = IFT_ATM;
361 ifp->if_addrlen = 0;
362 ifp->if_hdrlen = 0;
363 ifp->if_mtu = ATMMTU;
364 ifp->if_output = atm_output;
365
366#if defined(__NetBSD__) || defined(__OpenBSD__)
367 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
368 ifa = ifa->ifa_list.tqe_next)
369#elif defined(__FreeBSD__) && ((__FreeBSD__ > 2) || defined(_NET_IF_VAR_H_))
370/*
371 * for FreeBSD-3.0. 3.0-SNAP-970124 still sets -D__FreeBSD__=2!
372 * XXX -- for now, use newly-introduced "net/if_var.h" as an identifier.
373 * need a better way to identify 3.0. -- kjc
374 */
375 for (ifa = ifp->if_addrhead.tqh_first; ifa;
376 ifa = ifa->ifa_link.tqe_next)
377#elif defined(__FreeBSD__) || defined(__bsdi__)
378 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
379#endif
380
381 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
382 sdl->sdl_family == AF_LINK) {
383 sdl->sdl_type = IFT_ATM;
384 sdl->sdl_alen = ifp->if_addrlen;
385#ifdef notyet /* if using ATMARP, store hardware address using the next line */
386 bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
387#endif
388 break;
389 }
390#if NBPFILTER > 0
391#if defined(__NetBSD__) || defined(__OpenBSD__)
392 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
393#elif defined(__FreeBSD__)
394 bpfattach(ifp, DLT_NULL, sizeof(u_int));
395#endif
396#endif /* NBPFILTER > 0 */
397}
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
35/*
36 * if_atmsubr.c
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/mbuf.h>
42#include <sys/socket.h>
43
44#include <net/if.h>
45#include <net/netisr.h>
46#include <net/route.h>
47#include <net/if_dl.h>
48#include <net/if_types.h>
49#include <net/if_atm.h>
50
51#include <netinet/in.h>
52#include <netinet/if_atm.h>
53#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
54#ifdef INET
55#include <netinet/in_var.h>
56#endif
57#ifdef NATM
58#include <netnatm/natm.h>
59#endif
60
61#include "bpfilter.h"
62#if NBPFILTER > 0
63/*
64 * bpf support.
65 * the code is derived from if_loop.c.
66 * bpf support should belong to the driver but it's easier to implement
67 * it here since we can call bpf_mtap before atm_output adds a pseudo
68 * header to the mbuf.
69 * --kjc
70 */
71#include <net/bpf.h>
72#endif /* NBPFILTER > 0 */
73
74#define senderr(e) { error = (e); goto bad;}
75
76/*
77 * atm_output: ATM output routine
78 * inputs:
79 * "ifp" = ATM interface to output to
80 * "m0" = the packet to output
81 * "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
82 * "rt0" = the route to use
83 * returns: error code [0 == ok]
84 *
85 * note: special semantic: if (dst == NULL) then we assume "m" already
86 * has an atm_pseudohdr on it and just send it directly.
87 * [for native mode ATM output] if dst is null, then
88 * rt0 must also be NULL.
89 */
90
91int
92atm_output(ifp, m0, dst, rt0)
93 register struct ifnet *ifp;
94 struct mbuf *m0;
95 struct sockaddr *dst;
96 struct rtentry *rt0;
97{
98 u_int16_t etype = 0; /* if using LLC/SNAP */
99 int s, error = 0, sz;
100 struct atm_pseudohdr atmdst, *ad;
101 register struct mbuf *m = m0;
102 register struct rtentry *rt;
103 struct atmllc *atmllc;
104 u_int32_t atm_flags;
105
106 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
107 senderr(ENETDOWN);
108 gettime(&ifp->if_lastchange);
109
110 /*
111 * check route
112 */
113 if ((rt = rt0) != NULL) {
114
115 if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */
116 if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL)
117 rt->rt_refcnt--;
118 else
119 senderr(EHOSTUNREACH);
120 }
121
122 if (rt->rt_flags & RTF_GATEWAY) {
123 if (rt->rt_gwroute == 0)
124 goto lookup;
125 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
126 rtfree(rt); rt = rt0;
127 lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0);
128 if ((rt = rt->rt_gwroute) == 0)
129 senderr(EHOSTUNREACH);
130 }
131 }
132
133 /* XXX: put RTF_REJECT code here if doing ATMARP */
134
135 }
136
137 /*
138 * check for non-native ATM traffic (dst != NULL)
139 */
140 if (dst) {
141 switch (dst->sa_family) {
142#ifdef INET
143 case AF_INET:
144 if (!atmresolve(rt, m, dst, &atmdst)) {
145 m = NULL;
146 /* XXX: atmresolve already free'd it */
147 senderr(EHOSTUNREACH);
148 /* XXX: put ATMARP stuff here */
149 /* XXX: watch who frees m on failure */
150 }
151 etype = htons(ETHERTYPE_IP);
152 break;
153#endif
154
155 default:
156#if defined(__NetBSD__) || defined(__OpenBSD__)
157 printf("%s: can't handle af%d\n", ifp->if_xname,
158 dst->sa_family);
159#elif defined(__FreeBSD__) || defined(__bsdi__)
160 printf("%s%d: can't handle af%d\n", ifp->if_name,
161 ifp->if_unit, dst->sa_family);
162#endif
163 senderr(EAFNOSUPPORT);
164 }
165
166#if NBPFILTER > 0
167 /* BPF write needs to be handled specially */
168 if (dst && dst->sa_family == AF_UNSPEC) {
169 dst->sa_family = *(mtod(m, int *));
170 m->m_len -= sizeof(int);
171 m->m_pkthdr.len -= sizeof(int);
172 m->m_data += sizeof(int);
173 }
174
175 if (ifp->if_bpf) {
176 /*
177 * We need to prepend the address family as
178 * a four byte field. Cons up a dummy header
179 * to pacify bpf. This is safe because bpf
180 * will only read from the mbuf (i.e., it won't
181 * try to free it or keep a pointer a to it).
182 */
183 struct mbuf m1;
184 u_int af = dst->sa_family;
185
186 m1.m_next = m;
187 m1.m_len = 4;
188 m1.m_data = (char *)⁡
189
190 s = splimp();
191#if defined(__NetBSD__) || defined(__OpenBSD__)
192 bpf_mtap(&ifp->if_bpf, &m0);
193#elif defined(__FreeBSD__)
194 bpf_mtap(ifp, &m1);
195#endif
196 splx(s);
197 }
198#endif /* NBPFILTER > 0 */
199
200 /*
201 * must add atm_pseudohdr to data
202 */
203 sz = sizeof(atmdst);
204 atm_flags = ATM_PH_FLAGS(&atmdst);
205 if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */
206 M_PREPEND(m, sz, M_DONTWAIT);
207 if (m == 0)
208 senderr(ENOBUFS);
209 ad = mtod(m, struct atm_pseudohdr *);
210 *ad = atmdst;
211 if (atm_flags & ATM_PH_LLCSNAP) {
212 atmllc = (struct atmllc *)(ad + 1);
213 bcopy(ATMLLC_HDR, atmllc->llchdr,
214 sizeof(atmllc->llchdr));
215 ATM_LLC_SETTYPE(atmllc, etype);
216 /* note: already in network order */
217 }
218 }
219
220 /*
221 * Queue message on interface, and start output if interface
222 * not yet active.
223 */
224
225 s = splimp();
226 if (IF_QFULL(&ifp->if_snd)) {
227 IF_DROP(&ifp->if_snd);
228 splx(s);
229 senderr(ENOBUFS);
230 }
231 ifp->if_obytes += m->m_pkthdr.len;
232 IF_ENQUEUE(&ifp->if_snd, m);
233 if ((ifp->if_flags & IFF_OACTIVE) == 0)
234 (*ifp->if_start)(ifp);
235 splx(s);
236 return (error);
237
238bad:
239 if (m)
240 m_freem(m);
241 return (error);
242}
243
244/*
245 * Process a received ATM packet;
246 * the packet is in the mbuf chain m.
247 */
248void
249atm_input(ifp, ah, m, rxhand)
250 struct ifnet *ifp;
251 register struct atm_pseudohdr *ah;
252 struct mbuf *m;
253 void *rxhand;
254{
255 register struct ifqueue *inq;
256 u_int16_t etype = ETHERTYPE_IP; /* default */
257 int s;
258
259 if ((ifp->if_flags & IFF_UP) == 0) {
260 m_freem(m);
261 return;
262 }
263 gettime(&ifp->if_lastchange);
264 ifp->if_ibytes += m->m_pkthdr.len;
265
266#if NBPFILTER > 0
267 if (ifp->if_bpf) {
268 /*
269 * We need to prepend the address family as
270 * a four byte field. Cons up a dummy header
271 * to pacify bpf. This is safe because bpf
272 * will only read from the mbuf (i.e., it won't
273 * try to free it or keep a pointer to it).
274 */
275 struct mbuf m0;
276 u_int af = AF_INET;
277
278 m0.m_next = m;
279 m0.m_len = 4;
280 m0.m_data = (char *)⁡
281
282#if defined(__NetBSD__) || defined(__OpenBSD__)
283 bpf_mtap(&ifp->if_bpf, &m0);
284#elif defined(__FreeBSD__)
285 bpf_mtap(ifp, &m0);
286#endif
287 }
288#endif /* NBPFILTER > 0 */
289
290 if (rxhand) {
291#ifdef NATM
292 struct natmpcb *npcb = rxhand;
293 s = splimp(); /* in case 2 atm cards @ diff lvls */
294 npcb->npcb_inq++; /* count # in queue */
295 splx(s);
296 schednetisr(NETISR_NATM);
297 inq = &natmintrq;
298 m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
299#else
300 printf("atm_input: NATM detected but not configured in kernel\n");
301 m_freem(m);
302 return;
303#endif
304 } else {
305 /*
306 * handle LLC/SNAP header, if present
307 */
308 if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
309 struct atmllc *alc;
310 if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0)
311 return; /* failed */
312 alc = mtod(m, struct atmllc *);
313 if (bcmp(alc, ATMLLC_HDR, 6)) {
314#if defined(__NetBSD__) || defined(__OpenBSD__)
315 printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
316 ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
317#elif defined(__FreeBSD__) || defined(__bsdi__)
318 printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
319 ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
320#endif
321 m_freem(m);
322 return;
323 }
324 etype = ATM_LLC_TYPE(alc);
325 m_adj(m, sizeof(*alc));
326 }
327
328 switch (etype) {
329#ifdef INET
330 case ETHERTYPE_IP:
331 schednetisr(NETISR_IP);
332 inq = &ipintrq;
333 break;
334#endif
335 default:
336 m_freem(m);
337 return;
338 }
339 }
340
341 s = splimp();
342 if (IF_QFULL(inq)) {
343 IF_DROP(inq);
344 m_freem(m);
345 } else
346 IF_ENQUEUE(inq, m);
347 splx(s);
348}
349
350/*
351 * Perform common duties while attaching to interface list
352 */
353void
354atm_ifattach(ifp)
355 register struct ifnet *ifp;
356{
357 register struct ifaddr *ifa;
358 register struct sockaddr_dl *sdl;
359
360 ifp->if_type = IFT_ATM;
361 ifp->if_addrlen = 0;
362 ifp->if_hdrlen = 0;
363 ifp->if_mtu = ATMMTU;
364 ifp->if_output = atm_output;
365
366#if defined(__NetBSD__) || defined(__OpenBSD__)
367 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
368 ifa = ifa->ifa_list.tqe_next)
369#elif defined(__FreeBSD__) && ((__FreeBSD__ > 2) || defined(_NET_IF_VAR_H_))
370/*
371 * for FreeBSD-3.0. 3.0-SNAP-970124 still sets -D__FreeBSD__=2!
372 * XXX -- for now, use newly-introduced "net/if_var.h" as an identifier.
373 * need a better way to identify 3.0. -- kjc
374 */
375 for (ifa = ifp->if_addrhead.tqh_first; ifa;
376 ifa = ifa->ifa_link.tqe_next)
377#elif defined(__FreeBSD__) || defined(__bsdi__)
378 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
379#endif
380
381 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
382 sdl->sdl_family == AF_LINK) {
383 sdl->sdl_type = IFT_ATM;
384 sdl->sdl_alen = ifp->if_addrlen;
385#ifdef notyet /* if using ATMARP, store hardware address using the next line */
386 bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
387#endif
388 break;
389 }
390#if NBPFILTER > 0
391#if defined(__NetBSD__) || defined(__OpenBSD__)
392 bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
393#elif defined(__FreeBSD__)
394 bpfattach(ifp, DLT_NULL, sizeof(u_int));
395#endif
396#endif /* NBPFILTER > 0 */
397}