|
|
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];
1.1.1.2 ! root 92: #ifdef INET
1.1 root 93: struct in_addr idst;
1.1.1.2 ! root 94: #endif
1.1 root 95: register struct mbuf *m = m0;
96: struct mbuf *mcopy = (struct mbuf *)0;
97: register struct ether_header *eh;
98: int usetrailers, off, len = m->m_pkthdr.len;
99: #define ac ((struct arpcom *)ifp)
100:
101: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
102: error = ENETDOWN;
103: goto bad;
104: }
105: ifp->if_lastchange = time;
106: switch (dst->sa_family) {
107:
108: #ifdef INET
109: case AF_INET:
110: idst = ((struct sockaddr_in *)dst)->sin_addr;
111: if (!arpresolve(ac, m, &idst, edst, &usetrailers))
112: return (0); /* if not yet resolved */
113: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1))
114: mcopy = m_copy(m, 0, (int)M_COPYALL);
115: off = m->m_pkthdr.len - m->m_len;
116: if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
117: (m->m_flags & M_EXT) == 0 &&
118: m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) {
119: type = ETHERTYPE_TRAIL + (off>>9);
120: m->m_data -= 2 * sizeof (u_short);
121: m->m_len += 2 * sizeof (u_short);
122: len += 2 * sizeof (u_short);
123: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
124: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
125: goto gottrailertype;
126: }
127: type = ETHERTYPE_IP;
128: goto gottype;
129: #endif
130: #ifdef NS
131: case AF_NS:
132: type = ETHERTYPE_NS;
133: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
134: (caddr_t)edst, sizeof (edst));
135: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
136: return (looutput(ifp, m, dst, rt));
137: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1))
138: mcopy = m_copy(m, 0, (int)M_COPYALL);
139: goto gottype;
140: #endif
141: #ifdef ISO
142: case AF_ISO: {
143: int snpalen;
144: struct llc *l;
145:
146: iso_again:
147: if (rt && rt->rt_gateway && (rt->rt_flags & RTF_UP)) {
148: if (rt->rt_flags & RTF_GATEWAY) {
149: if (rt->rt_llinfo) {
150: rt = (struct rtentry *)rt->rt_llinfo;
151: goto iso_again;
152: }
153: } else {
154: register struct sockaddr_dl *sdl =
155: (struct sockaddr_dl *)rt->rt_gateway;
156: if (sdl && sdl->sdl_family == AF_LINK
157: && sdl->sdl_alen > 0) {
158: bcopy(LLADDR(sdl), (char *)edst,
159: sizeof(edst));
160: goto iso_resolved;
161: }
162: }
163: }
164: if ((error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
165: (char *)edst, &snpalen)) > 0)
166: goto bad; /* Not Resolved */
167: iso_resolved:
168: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
169: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
170: M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
171: if (mcopy) {
172: eh = mtod(mcopy, struct ether_header *);
173: bcopy((caddr_t)edst,
174: (caddr_t)eh->ether_dhost, sizeof (edst));
175: bcopy((caddr_t)ac->ac_enaddr,
176: (caddr_t)eh->ether_shost, sizeof (edst));
177: }
178: }
179: M_PREPEND(m, 3, M_DONTWAIT);
180: if (m == NULL)
181: return (0);
182: type = m->m_pkthdr.len;
183: l = mtod(m, struct llc *);
184: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
185: l->llc_control = LLC_UI;
186: len += 3;
187: IFDEBUG(D_ETHER)
188: int i;
189: printf("unoutput: sending pkt to: ");
190: for (i=0; i<6; i++)
191: printf("%x ", edst[i] & 0xff);
192: printf("\n");
193: ENDDEBUG
194: } goto gottype;
195: #endif ISO
196: #ifdef RMP
197: case AF_RMP:
198: /*
199: * This is IEEE 802.3 -- the Ethernet `type' field is
200: * really a `length' field.
201: */
202: type = m->m_len;
203: bcopy((caddr_t)dst->sa_data, (caddr_t)edst, sizeof(edst));
204: break;
205: #endif
206:
207: case AF_UNSPEC:
208: eh = (struct ether_header *)dst->sa_data;
209: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
210: type = eh->ether_type;
211: goto gottype;
212:
213: default:
214: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
215: dst->sa_family);
216: error = EAFNOSUPPORT;
217: goto bad;
218: }
219:
220: gottrailertype:
221: /*
222: * Packet to be sent as trailer: move first packet
223: * (control information) to end of chain.
224: */
225: while (m->m_next)
226: m = m->m_next;
227: m->m_next = m0;
228: m = m0->m_next;
229: m0->m_next = 0;
230:
231: gottype:
232: if (mcopy)
233: (void) looutput(ifp, mcopy, dst, rt);
234: /*
235: * Add local net header. If no space in first mbuf,
236: * allocate another.
237: */
238: M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
239: if (m == 0) {
240: error = ENOBUFS;
241: goto bad;
242: }
243: eh = mtod(m, struct ether_header *);
244: type = htons((u_short)type);
245: bcopy((caddr_t)&type,(caddr_t)&eh->ether_type,
246: sizeof(eh->ether_type));
247: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
248: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
249: sizeof(eh->ether_shost));
250: s = splimp();
251: /*
252: * Queue message on interface, and start output if interface
253: * not yet active.
254: */
255: if (IF_QFULL(&ifp->if_snd)) {
256: IF_DROP(&ifp->if_snd);
257: splx(s);
258: error = ENOBUFS;
259: goto bad;
260: }
261: IF_ENQUEUE(&ifp->if_snd, m);
262: if ((ifp->if_flags & IFF_OACTIVE) == 0)
263: (*ifp->if_start)(ifp);
264: splx(s);
265: ifp->if_obytes += len + sizeof (struct ether_header);
266: if (edst[0] & 1)
267: ifp->if_omcasts++;
268: return (error);
269:
270: bad:
271: if (m)
272: m_freem(m);
273: return (error);
274: }
275:
276: /*
277: * Process a received Ethernet packet;
278: * the packet is in the mbuf chain m without
279: * the ether header, which is provided separately.
280: */
281: ether_input(ifp, eh, m)
282: struct ifnet *ifp;
283: register struct ether_header *eh;
284: struct mbuf *m;
285: {
286: register struct ifqueue *inq;
287: register struct llc *l;
288: int s;
289:
290: ifp->if_lastchange = time;
291: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
292: if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
293: sizeof(etherbroadcastaddr)) == 0)
294: m->m_flags |= M_BCAST;
295: else if (eh->ether_dhost[0] & 1)
296: m->m_flags |= M_MCAST;
297: if (m->m_flags & (M_BCAST|M_MCAST))
298: ifp->if_imcasts++;
299:
300: switch (eh->ether_type) {
301: #ifdef INET
302: case ETHERTYPE_IP:
303: schednetisr(NETISR_IP);
304: inq = &ipintrq;
305: break;
306:
307: case ETHERTYPE_ARP:
308: arpinput((struct arpcom *)ifp, m);
309: return;
310: #endif
311: #ifdef NS
312: case ETHERTYPE_NS:
313: schednetisr(NETISR_NS);
314: inq = &nsintrq;
315: break;
316:
317: #endif
318: default:
319: #ifdef ISO
320: if (eh->ether_type > ETHERMTU)
321: goto dropanyway;
322: l = mtod(m, struct llc *);
323: switch (l->llc_control) {
324: case LLC_UI:
325: /* LLC_UI_P forbidden in class 1 service */
326: if ((l->llc_dsap == LLC_ISO_LSAP) &&
327: (l->llc_ssap == LLC_ISO_LSAP)) {
328: /* LSAP for ISO */
329: if (m->m_pkthdr.len > eh->ether_type)
330: m_adj(m, eh->ether_type - m->m_pkthdr.len);
331: m->m_data += 3; /* XXX */
332: m->m_len -= 3; /* XXX */
333: m->m_pkthdr.len -= 3; /* XXX */
334: M_PREPEND(m, sizeof *eh, M_DONTWAIT);
335: if (m == 0)
336: return;
337: *mtod(m, struct ether_header *) = *eh;
338: IFDEBUG(D_ETHER)
339: printf("clnp packet");
340: ENDDEBUG
341: schednetisr(NETISR_ISO);
342: inq = &clnlintrq;
343: break;
344: }
345: goto dropanyway;
346:
347: case LLC_XID:
348: case LLC_XID_P:
349: if(m->m_len < 6)
350: goto dropanyway;
351: l->llc_window = 0;
352: l->llc_fid = 9;
353: l->llc_class = 1;
354: l->llc_dsap = l->llc_ssap = 0;
355: /* Fall through to */
356: case LLC_TEST:
357: case LLC_TEST_P:
358: {
359: struct sockaddr sa;
360: register struct ether_header *eh2;
361: int i;
362: u_char c = l->llc_dsap;
363: l->llc_dsap = l->llc_ssap;
364: l->llc_ssap = c;
365: if (m->m_flags & (M_BCAST | M_MCAST))
366: bcopy((caddr_t)ac->ac_enaddr,
367: (caddr_t)eh->ether_dhost, 6);
368: sa.sa_family = AF_UNSPEC;
369: sa.sa_len = sizeof(sa);
370: eh2 = (struct ether_header *)sa.sa_data;
371: for (i = 0; i < 6; i++) {
372: eh2->ether_shost[i] = c = eh->ether_dhost[i];
373: eh2->ether_dhost[i] =
374: eh->ether_dhost[i] = eh->ether_shost[i];
375: eh->ether_shost[i] = c;
376: }
377: ifp->if_output(ifp, m, &sa);
378: return;
379: }
380: dropanyway:
381: default:
382: m_freem(m);
383: return;
384: }
385: #else
386: m_freem(m);
387: return;
388: #endif ISO
389: }
390:
391: s = splimp();
392: if (IF_QFULL(inq)) {
393: IF_DROP(inq);
394: m_freem(m);
395: } else
396: IF_ENQUEUE(inq, m);
397: splx(s);
398: }
399:
400: /*
401: * Convert Ethernet address to printable (loggable) representation.
402: */
403: static char digits[] = "0123456789abcdef";
404: char *
405: ether_sprintf(ap)
406: register u_char *ap;
407: {
408: register i;
409: static char etherbuf[18];
410: register char *cp = etherbuf;
411:
412: for (i = 0; i < 6; i++) {
413: *cp++ = digits[*ap >> 4];
414: *cp++ = digits[*ap++ & 0xf];
415: *cp++ = ':';
416: }
417: *--cp = 0;
418: return (etherbuf);
419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.