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