Annotation of sys/net/if_fddisubr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_fddisubr.c,v 1.52 2007/06/06 10:04:36 henning Exp $ */
2: /* $NetBSD: if_fddisubr.c,v 1.5 1996/05/07 23:20:21 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1995
6: * Matt Thomas. All rights reserved.
7: * Copyright (c) 1982, 1989, 1993
8: * The Regents of the University of California. All rights reserved.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * @(#)if_fddisubr.c 8.1 (Berkeley) 6/10/93
35: */
36:
37: /*
38: * @(#)COPYRIGHT 1.1 (NRL) January 1997
39: *
40: * NRL grants permission for redistribution and use in source and binary
41: * forms, with or without modification, of the software and documentation
42: * created at NRL provided that the following conditions are met:
43: *
44: * 1. Redistributions of source code must retain the above copyright
45: * notice, this list of conditions and the following disclaimer.
46: * 2. Redistributions in binary form must reproduce the above copyright
47: * notice, this list of conditions and the following disclaimer in the
48: * documentation and/or other materials provided with the distribution.
49: * 3. All advertising materials mentioning features or use of this software
50: * must display the following acknowledgements:
51: * This product includes software developed by the University of
52: * California, Berkeley and its contributors.
53: * This product includes software developed at the Information
54: * Technology Division, US Naval Research Laboratory.
55: * 4. Neither the name of the NRL nor the names of its contributors
56: * may be used to endorse or promote products derived from this software
57: * without specific prior written permission.
58: *
59: * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
60: * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
61: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
62: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
63: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
64: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
65: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
66: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
67: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
68: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
69: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70: *
71: * The views and conclusions contained in the software and documentation
72: * are those of the authors and should not be interpreted as representing
73: * official policies, either expressed or implied, of the US Naval
74: * Research Laboratory (NRL).
75: */
76:
77: #include <sys/param.h>
78: #include <sys/systm.h>
79: #include <sys/kernel.h>
80: #include <sys/malloc.h>
81: #include <sys/mbuf.h>
82: #include <sys/protosw.h>
83: #include <sys/socket.h>
84: #include <sys/ioctl.h>
85: #include <sys/errno.h>
86: #include <sys/syslog.h>
87:
88: #include <machine/cpu.h>
89:
90: #include <net/if.h>
91: #include <net/netisr.h>
92: #include <net/route.h>
93: #include <net/if_llc.h>
94: #include <net/if_dl.h>
95: #include <net/if_types.h>
96:
97: #ifdef INET
98: #include <netinet/in.h>
99: #include <netinet/in_var.h>
100: #endif
101: #include <netinet/if_ether.h>
102: #include <net/if_fddi.h>
103:
104: #ifdef INET6
105: #ifndef INET
106: #include <netinet/in.h>
107: #include <netinet/in_var.h>
108: #endif
109: #include <netinet6/nd6.h>
110: #endif
111:
112: #include "bpfilter.h"
113:
114: #include "carp.h"
115: #if NCARP > 0
116: #include <netinet/ip_carp.h>
117: #endif
118:
119: #define senderr(e) { error = (e); goto bad;}
120:
121: /*
122: * This really should be defined in if_llc.h but in case it isn't.
123: */
124: #ifndef llc_snap
125: #define llc_snap llc_un.type_snap
126: #endif
127:
128: /*
129: * FDDI output routine.
130: * Encapsulate a packet of type family for the local net.
131: * Assumes that ifp is actually pointer to arpcom structure.
132: */
133: int
134: fddi_output(ifp0, m0, dst, rt0)
135: struct ifnet *ifp0;
136: struct mbuf *m0;
137: struct sockaddr *dst;
138: struct rtentry *rt0;
139: {
140: u_int16_t type;
141: int s, len, error = 0, hdrcmplt = 0;
142: u_char edst[6], esrc[6];
143: struct mbuf *m = m0;
144: struct rtentry *rt;
145: struct mbuf *mcopy = (struct mbuf *)0;
146: struct fddi_header *fh;
147: struct arpcom *ac = (struct arpcom *)ifp0;
148: short mflags;
149: struct ifnet *ifp = ifp0;
150:
151: #if NCARP > 0
152: if (ifp->if_type == IFT_CARP) {
153: struct ifaddr *ifa;
154:
155: /* loop back if this is going to the carp interface */
156: if (dst != NULL && LINK_STATE_IS_UP(ifp0->if_link_state) &&
157: (ifa = ifa_ifwithaddr(dst)) != NULL &&
158: ifa->ifa_ifp == ifp0)
159: return (looutput(ifp0, m, dst, rt0));
160:
161: ifp = ifp->if_carpdev;
162: ac = (struct arpcom *)ifp;
163:
164: if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
165: (IFF_UP|IFF_RUNNING))
166: senderr(ENETDOWN);
167: }
168: #endif /* NCARP > 0 */
169: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
170: senderr(ENETDOWN);
171: if ((rt = rt0) != NULL) {
172: if ((rt->rt_flags & RTF_UP) == 0) {
173: if ((rt0 = rt = rtalloc1(dst, 1, 0)) != NULL)
174: rt->rt_refcnt--;
175: else
176: senderr(EHOSTUNREACH);
177: }
178: if (rt->rt_flags & RTF_GATEWAY) {
179: if (rt->rt_gwroute == 0)
180: goto lookup;
181: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
182: rtfree(rt); rt = rt0;
183: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0);
184: if ((rt = rt->rt_gwroute) == 0)
185: senderr(EHOSTUNREACH);
186: }
187: }
188: if (rt->rt_flags & RTF_REJECT)
189: if (rt->rt_rmx.rmx_expire == 0 ||
190: time_second < rt->rt_rmx.rmx_expire)
191: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
192: }
193:
194: switch (dst->sa_family) {
195:
196: #ifdef INET
197: case AF_INET:
198: if (!arpresolve(ac, rt, m, dst, edst))
199: return (0); /* if not yet resolved */
200: /* If broadcasting on a simplex interface, loopback a copy */
201: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
202: !m->m_pkthdr.pf.routed)
203: mcopy = m_copy(m, 0, (int)M_COPYALL);
204: type = htons(ETHERTYPE_IP);
205: break;
206: #endif
207: #ifdef INET6
208: case AF_INET6:
209: if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
210: return (0); /* if not yet resolved */
211: type = htons(ETHERTYPE_IPV6);
212: break;
213: #endif
214: #if 0 /*NRL IPv6*/
215: #ifdef INET6
216: case AF_INET6:
217: /*
218: * The bottom line here is to either queue the outgoing packet
219: * in the discovery engine, or fill in edst with something
220: * that'll work.
221: */
222: if (m->m_flags & M_MCAST) {
223: /*
224: * If multicast dest., then use IPv6 -> Ethernet mcast
225: * mapping. Really simple.
226: */
227: ETHER_MAP_IN6_MULTICAST(((struct sockaddr_in6 *)dst)->sin6_addr,
228: edst);
229: } else {
230: /* Do unicast neighbor discovery stuff. */
231: if (!ipv6_discov_resolve(ifp, rt, m, dst, edst))
232: return 0;
233: }
234: type = htons(ETHERTYPE_IPV6);
235: break;
236: #endif /* INET6 */
237: #endif
238:
239: case pseudo_AF_HDRCMPLT:
240: {
241: struct fddi_header *fh = (struct fddi_header *)dst->sa_data;
242: hdrcmplt = 1;
243: bcopy((caddr_t)fh->fddi_shost, (caddr_t)esrc, sizeof (esrc));
244: /* FALLTHROUGH */
245: }
246:
247: case AF_UNSPEC:
248: {
249: struct ether_header *eh;
250: eh = (struct ether_header *)dst->sa_data;
251: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
252: if (*edst & 1)
253: m->m_flags |= (M_BCAST|M_MCAST);
254: type = eh->ether_type;
255: break;
256: }
257:
258: #if NBPFILTER > 0
259: case AF_IMPLINK:
260: {
261: fh = mtod(m, struct fddi_header *);
262: error = EPROTONOSUPPORT;
263: switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
264: case FDDIFC_LLC_ASYNC: {
265: /* legal priorities are 0 through 7 */
266: if ((fh->fddi_fc & FDDIFC_Z) > 7)
267: goto bad;
268: break;
269: }
270: case FDDIFC_LLC_SYNC: {
271: /* FDDIFC_Z bits reserved, must be zero */
272: if (fh->fddi_fc & FDDIFC_Z)
273: goto bad;
274: break;
275: }
276: case FDDIFC_SMT: {
277: /* FDDIFC_Z bits must be non zero */
278: if ((fh->fddi_fc & FDDIFC_Z) == 0)
279: goto bad;
280: break;
281: }
282: default: {
283: /* anything else is too dangerous */
284: goto bad;
285: }
286: }
287: error = 0;
288: if (fh->fddi_dhost[0] & 1)
289: m->m_flags |= (M_BCAST|M_MCAST);
290: goto queue_it;
291: }
292: #endif
293: default:
294: printf("%s: can't handle af%d\n", ifp->if_xname,
295: dst->sa_family);
296: senderr(EAFNOSUPPORT);
297: }
298:
299: if (mcopy)
300: (void) looutput(ifp, mcopy, dst, rt);
301:
302: if (type != 0) {
303: struct llc *l;
304: M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
305: if (m == 0)
306: senderr(ENOBUFS);
307: l = mtod(m, struct llc *);
308: l->llc_control = LLC_UI;
309: l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
310: l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
311: bcopy((caddr_t) &type, (caddr_t) &l->llc_snap.ether_type,
312: sizeof(u_short));
313: }
314: /*
315: * Add local net header. If no space in first mbuf,
316: * allocate another.
317: */
318: M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
319: if (m == 0)
320: senderr(ENOBUFS);
321: fh = mtod(m, struct fddi_header *);
322: fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
323: bcopy((caddr_t)edst, (caddr_t)fh->fddi_dhost, sizeof (edst));
324: #if NBPFILTER > 0
325: queue_it:
326: #endif
327: if (hdrcmplt)
328: bcopy((caddr_t)esrc, (caddr_t)fh->fddi_shost,
329: sizeof(fh->fddi_shost));
330: else
331: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)fh->fddi_shost,
332: sizeof(fh->fddi_shost));
333: #if NCARP > 0
334: if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
335: bcopy((caddr_t)((struct arpcom *)ifp0)->ac_enaddr,
336: (caddr_t)fh->fddi_shost, sizeof(fh->fddi_shost));
337: }
338: #endif
339: mflags = m->m_flags;
340: len = m->m_pkthdr.len;
341: s = splnet();
342: /*
343: * Queue message on interface, and start output if interface
344: * not yet active.
345: */
346: IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
347: if (error) {
348: /* mbuf is already freed */
349: splx(s);
350: return (error);
351: }
352: ifp->if_obytes += len;
353: #if NCARP > 0
354: if (ifp != ifp0)
355: ifp0->if_obytes += len;
356: #endif /* NCARP > 0 */
357: if (mflags & M_MCAST)
358: ifp->if_omcasts++;
359: if ((ifp->if_flags & IFF_OACTIVE) == 0)
360: (*ifp->if_start)(ifp);
361: splx(s);
362: return (error);
363:
364: bad:
365: if (m)
366: m_freem(m);
367: return (error);
368: }
369:
370: /*
371: * Process a received FDDI packet;
372: * the packet is in the mbuf chain m without
373: * the fddi header, which is provided separately.
374: */
375: void
376: fddi_input(ifp, fh, m)
377: struct ifnet *ifp;
378: struct fddi_header *fh;
379: struct mbuf *m;
380: {
381: struct ifqueue *inq;
382: struct llc *l;
383: int s;
384:
385: if ((ifp->if_flags & IFF_UP) == 0) {
386: m_freem(m);
387: return;
388: }
389: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh);
390: if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
391: sizeof(fddibroadcastaddr)) == 0)
392: m->m_flags |= M_BCAST;
393: else if (fh->fddi_dhost[0] & 1)
394: m->m_flags |= M_MCAST;
395: if (m->m_flags & (M_BCAST|M_MCAST))
396: ifp->if_imcasts++;
397:
398: l = mtod(m, struct llc *);
399: switch (l->llc_dsap) {
400: #if defined(INET) || defined(INET6)
401: case LLC_SNAP_LSAP:
402: {
403: u_int16_t etype;
404: if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
405: goto dropanyway;
406: if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
407: goto dropanyway;
408: etype = ntohs(l->llc_snap.ether_type);
409: m_adj(m, LLC_SNAPFRAMELEN);
410:
411: #if NCARP > 0
412: if (ifp->if_carp && ifp->if_type != IFT_CARP &&
413: (carp_input(m, (u_int8_t *)&fh->fddi_shost,
414: (u_int8_t *)&fh->fddi_dhost, l->llc_snap.ether_type) == 0))
415: return;
416: #endif
417:
418: switch (etype) {
419: #ifdef INET
420: case ETHERTYPE_IP:
421: schednetisr(NETISR_IP);
422: inq = &ipintrq;
423: break;
424:
425: case ETHERTYPE_ARP:
426: if (ifp->if_flags & IFF_NOARP)
427: goto dropanyway;
428: schednetisr(NETISR_ARP);
429: inq = &arpintrq;
430: break;
431: #endif
432: #ifdef INET6
433: case ETHERTYPE_IPV6:
434: schednetisr(NETISR_IPV6);
435: inq = &ip6intrq;
436: break;
437: #endif /* INET6 */
438: default:
439: /* printf("fddi_input: unknown protocol 0x%x\n", etype); */
440: ifp->if_noproto++;
441: goto dropanyway;
442: }
443: break;
444: }
445: #endif /* INET || INET6 */
446:
447: default:
448: /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */
449: ifp->if_noproto++;
450: dropanyway:
451: m_freem(m);
452: return;
453: }
454:
455: s = splnet();
456: IF_INPUT_ENQUEUE(inq, m);
457: splx(s);
458: }
459: /*
460: * Perform common duties while attaching to interface list
461: */
462: void
463: fddi_ifattach(ifp)
464: struct ifnet *ifp;
465: {
466:
467: ifp->if_type = IFT_FDDI;
468: ifp->if_addrlen = 6;
469: ifp->if_hdrlen = 21;
470: ifp->if_mtu = FDDIMTU;
471: ifp->if_output = fddi_output;
472: if_alloc_sadl(ifp);
473: bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
474: LLADDR(ifp->if_sadl), ifp->if_addrlen);
475: }
CVSweb