|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)if_ethersubr.c 7.13 (Berkeley) 4/20/91
34: */
35:
36: #include "param.h"
37: #include "systm.h"
38: #include "kernel.h"
39: #include "malloc.h"
40: #include "mbuf.h"
41: #include "protosw.h"
42: #include "socket.h"
43: #include "ioctl.h"
44: #include "errno.h"
45: #include "syslog.h"
46:
47: #include "if.h"
48: #include "netisr.h"
49: #include "route.h"
50: #include "if_llc.h"
51: #include "if_dl.h"
52:
53: #include "machine/mtpr.h"
54:
55: #ifdef INET
56: #include "../netinet/in.h"
57: #include "../netinet/in_var.h"
58: #endif
59: #include "../netinet/if_ether.h"
60:
61: #ifdef NS
62: #include "../netns/ns.h"
63: #include "../netns/ns_if.h"
64: #endif
65:
66: #ifdef ISO
67: #include "../netiso/argo_debug.h"
68: #include "../netiso/iso.h"
69: #include "../netiso/iso_var.h"
70: #include "../netiso/iso_snpac.h"
71: #endif
72:
73: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
74: extern struct ifnet loif;
75:
76: /*
77: * Ethernet output routine.
78: * Encapsulate a packet of type family for the local net.
79: * Use trailer local net encapsulation if enough data in first
80: * packet leaves a multiple of 512 bytes of data in remainder.
81: * Assumes that ifp is actually pointer to arpcom structure.
82: */
83: ether_output(ifp, m0, dst, rt)
84: register struct ifnet *ifp;
85: struct mbuf *m0;
86: struct sockaddr *dst;
87: struct rtentry *rt;
88: {
89: short type;
90: int s, error = 0;
91: u_char edst[6];
92: struct in_addr idst;
93: register struct mbuf *m = m0;
94: struct mbuf *mcopy = (struct mbuf *)0;
95: register struct ether_header *eh;
96: int usetrailers, off, len = m->m_pkthdr.len;
97: #define ac ((struct arpcom *)ifp)
98:
99: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
100: error = ENETDOWN;
101: goto bad;
102: }
103: ifp->if_lastchange = time;
104: switch (dst->sa_family) {
105:
106: #ifdef INET
107: case AF_INET:
108: idst = ((struct sockaddr_in *)dst)->sin_addr;
109: if (!arpresolve(ac, m, &idst, edst, &usetrailers))
110: return (0); /* if not yet resolved */
111: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1))
112: mcopy = m_copy(m, 0, (int)M_COPYALL);
113: off = m->m_pkthdr.len - m->m_len;
114: if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
115: (m->m_flags & M_EXT) == 0 &&
116: m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) {
117: type = ETHERTYPE_TRAIL + (off>>9);
118: m->m_data -= 2 * sizeof (u_short);
119: m->m_len += 2 * sizeof (u_short);
120: len += 2 * sizeof (u_short);
121: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
122: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
123: goto gottrailertype;
124: }
125: type = ETHERTYPE_IP;
126: goto gottype;
127: #endif
128: #ifdef NS
129: case AF_NS:
130: type = ETHERTYPE_NS;
131: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
132: (caddr_t)edst, sizeof (edst));
133: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
134: return (looutput(ifp, m, dst, rt));
135: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1))
136: mcopy = m_copy(m, 0, (int)M_COPYALL);
137: goto gottype;
138: #endif
139: #ifdef ISO
140: case AF_ISO: {
141: int snpalen;
142: struct llc *l;
143:
144: iso_again:
145: if (rt && rt->rt_gateway && (rt->rt_flags & RTF_UP)) {
146: if (rt->rt_flags & RTF_GATEWAY) {
147: if (rt->rt_llinfo) {
148: rt = (struct rtentry *)rt->rt_llinfo;
149: goto iso_again;
150: }
151: } else {
152: register struct sockaddr_dl *sdl =
153: (struct sockaddr_dl *)rt->rt_gateway;
154: if (sdl && sdl->sdl_family == AF_LINK
155: && sdl->sdl_alen > 0) {
156: bcopy(LLADDR(sdl), (char *)edst,
157: sizeof(edst));
158: goto iso_resolved;
159: }
160: }
161: }
162: if ((error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
163: (char *)edst, &snpalen)) > 0)
164: goto bad; /* Not Resolved */
165: iso_resolved:
166: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
167: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
168: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
169: if (mcopy) {
170: eh = mtod(mcopy, struct ether_header *);
171: bcopy((caddr_t)edst,
172: (caddr_t)eh->ether_dhost, sizeof (edst));
173: bcopy((caddr_t)ac->ac_enaddr,
174: (caddr_t)eh->ether_shost, sizeof (edst));
175: }
176: }
177: M_PREPEND(m, 3, M_DONTWAIT);
178: if (m == NULL)
179: return (0);
180: type = m->m_pkthdr.len;
181: l = mtod(m, struct llc *);
182: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
183: l->llc_control = LLC_UI;
184: len += 3;
185: IFDEBUG(D_ETHER)
186: int i;
187: printf("unoutput: sending pkt to: ");
188: for (i=0; i<6; i++)
189: printf("%x ", edst[i] & 0xff);
190: printf("\n");
191: ENDDEBUG
192: } goto gottype;
193: #endif ISO
194: #ifdef RMP
195: case AF_RMP:
196: /*
197: * This is IEEE 802.3 -- the Ethernet `type' field is
198: * really a `length' field.
199: */
200: type = m->m_len;
201: bcopy((caddr_t)dst->sa_data, (caddr_t)edst, sizeof(edst));
202: break;
203: #endif
204:
205: case AF_UNSPEC:
206: eh = (struct ether_header *)dst->sa_data;
207: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
208: type = eh->ether_type;
209: goto gottype;
210:
211: default:
212: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
213: dst->sa_family);
214: error = EAFNOSUPPORT;
215: goto bad;
216: }
217:
218: gottrailertype:
219: /*
220: * Packet to be sent as trailer: move first packet
221: * (control information) to end of chain.
222: */
223: while (m->m_next)
224: m = m->m_next;
225: m->m_next = m0;
226: m = m0->m_next;
227: m0->m_next = 0;
228:
229: gottype:
230: if (mcopy)
231: (void) looutput(ifp, mcopy, dst, rt);
232: /*
233: * Add local net header. If no space in first mbuf,
234: * allocate another.
235: */
236: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
237: if (m == 0) {
238: error = ENOBUFS;
239: goto bad;
240: }
241: eh = mtod(m, struct ether_header *);
242: type = htons((u_short)type);
243: bcopy((caddr_t)&type,(caddr_t)&eh->ether_type,
244: sizeof(eh->ether_type));
245: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
246: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
247: sizeof(eh->ether_shost));
248: s = splimp();
249: /*
250: * Queue message on interface, and start output if interface
251: * not yet active.
252: */
253: if (IF_QFULL(&ifp->if_snd)) {
254: IF_DROP(&ifp->if_snd);
255: splx(s);
256: error = ENOBUFS;
257: goto bad;
258: }
259: IF_ENQUEUE(&ifp->if_snd, m);
260: if ((ifp->if_flags & IFF_OACTIVE) == 0)
261: (*ifp->if_start)(ifp);
262: splx(s);
263: ifp->if_obytes += len + sizeof (struct ether_header);
264: if (edst[0] & 1)
265: ifp->if_omcasts++;
266: return (error);
267:
268: bad:
269: if (m)
270: m_freem(m);
271: return (error);
272: }
273:
274: /*
275: * Process a received Ethernet packet;
276: * the packet is in the mbuf chain m without
277: * the ether header, which is provided separately.
278: */
279: ether_input(ifp, eh, m)
280: struct ifnet *ifp;
281: register struct ether_header *eh;
282: struct mbuf *m;
283: {
284: register struct ifqueue *inq;
285: register struct llc *l;
286: int s;
287:
288: ifp->if_lastchange = time;
289: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
290: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
291: sizeof(etherbroadcastaddr)) == 0)
292: m->m_flags |= M_BCAST;
293: else if (eh->ether_dhost[0] & 1)
294: m->m_flags |= M_MCAST;
295: if (m->m_flags & (M_BCAST|M_MCAST))
296: ifp->if_imcasts++;
297:
298: switch (eh->ether_type) {
299: #ifdef INET
300: case ETHERTYPE_IP:
301: schednetisr(NETISR_IP);
302: inq = &ipintrq;
303: break;
304:
305: case ETHERTYPE_ARP:
306: arpinput((struct arpcom *)ifp, m);
307: return;
308: #endif
309: #ifdef NS
310: case ETHERTYPE_NS:
311: schednetisr(NETISR_NS);
312: inq = &nsintrq;
313: break;
314:
315: #endif
316: default:
317: #ifdef ISO
318: if (eh->ether_type > ETHERMTU)
319: goto dropanyway;
320: l = mtod(m, struct llc *);
321: switch (l->llc_control) {
322: case LLC_UI:
323: /* LLC_UI_P forbidden in class 1 service */
324: if ((l->llc_dsap == LLC_ISO_LSAP) &&
325: (l->llc_ssap == LLC_ISO_LSAP)) {
326: /* LSAP for ISO */
327: if (m->m_pkthdr.len > eh->ether_type)
328: m_adj(m, eh->ether_type - m->m_pkthdr.len);
329: m->m_data += 3; /* XXX */
330: m->m_len -= 3; /* XXX */
331: m->m_pkthdr.len -= 3; /* XXX */
332: M_PREPEND(m, sizeof *eh, M_DONTWAIT);
333: if (m == 0)
334: return;
335: *mtod(m, struct ether_header *) = *eh;
336: IFDEBUG(D_ETHER)
337: printf("clnp packet");
338: ENDDEBUG
339: schednetisr(NETISR_ISO);
340: inq = &clnlintrq;
341: break;
342: }
343: goto dropanyway;
344:
345: case LLC_XID:
346: case LLC_XID_P:
347: if(m->m_len < 6)
348: goto dropanyway;
349: l->llc_window = 0;
350: l->llc_fid = 9;
351: l->llc_class = 1;
352: l->llc_dsap = l->llc_ssap = 0;
353: /* Fall through to */
354: case LLC_TEST:
355: case LLC_TEST_P:
356: {
357: struct sockaddr sa;
358: register struct ether_header *eh2;
359: int i;
360: u_char c = l->llc_dsap;
361: l->llc_dsap = l->llc_ssap;
362: l->llc_ssap = c;
363: if (m->m_flags & (M_BCAST | M_MCAST))
364: bcopy((caddr_t)ac->ac_enaddr,
365: (caddr_t)eh->ether_dhost, 6);
366: sa.sa_family = AF_UNSPEC;
367: sa.sa_len = sizeof(sa);
368: eh2 = (struct ether_header *)sa.sa_data;
369: for (i = 0; i < 6; i++) {
370: eh2->ether_shost[i] = c = eh->ether_dhost[i];
371: eh2->ether_dhost[i] =
372: eh->ether_dhost[i] = eh->ether_shost[i];
373: eh->ether_shost[i] = c;
374: }
375: ifp->if_output(ifp, m, &sa);
376: return;
377: }
378: dropanyway:
379: default:
380: m_freem(m);
381: return;
382: }
383: #else
384: m_freem(m);
385: return;
386: #endif ISO
387: }
388:
389: s = splimp();
390: if (IF_QFULL(inq)) {
391: IF_DROP(inq);
392: m_freem(m);
393: } else
394: IF_ENQUEUE(inq, m);
395: splx(s);
396: }
397:
398: /*
399: * Convert Ethernet address to printable (loggable) representation.
400: */
401: static char digits[] = "0123456789abcdef";
402: char *
403: ether_sprintf(ap)
404: register u_char *ap;
405: {
406: register i;
407: static char etherbuf[18];
408: register char *cp = etherbuf;
409:
410: for (i = 0; i < 6; i++) {
411: *cp++ = digits[*ap >> 4];
412: *cp++ = digits[*ap++ & 0xf];
413: *cp++ = ':';
414: }
415: *--cp = 0;
416: return (etherbuf);
417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.