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