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