1*ca987d46SWarner Losh /* $NetBSD: ether.c,v 1.11 1997/07/07 15:52:50 drochner Exp $ */
2*ca987d46SWarner Losh
3*ca987d46SWarner Losh /*
4*ca987d46SWarner Losh * Copyright (c) 1992 Regents of the University of California.
5*ca987d46SWarner Losh * All rights reserved.
6*ca987d46SWarner Losh *
7*ca987d46SWarner Losh * This software was developed by the Computer Systems Engineering group
8*ca987d46SWarner Losh * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9*ca987d46SWarner Losh * contributed to Berkeley.
10*ca987d46SWarner Losh *
11*ca987d46SWarner Losh * Redistribution and use in source and binary forms, with or without
12*ca987d46SWarner Losh * modification, are permitted provided that the following conditions
13*ca987d46SWarner Losh * are met:
14*ca987d46SWarner Losh * 1. Redistributions of source code must retain the above copyright
15*ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer.
16*ca987d46SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
17*ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer in the
18*ca987d46SWarner Losh * documentation and/or other materials provided with the distribution.
19*ca987d46SWarner Losh * 3. Neither the name of the University nor the names of its contributors
20*ca987d46SWarner Losh * may be used to endorse or promote products derived from this software
21*ca987d46SWarner Losh * without specific prior written permission.
22*ca987d46SWarner Losh *
23*ca987d46SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24*ca987d46SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*ca987d46SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*ca987d46SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27*ca987d46SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*ca987d46SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*ca987d46SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*ca987d46SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*ca987d46SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*ca987d46SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*ca987d46SWarner Losh * SUCH DAMAGE.
34*ca987d46SWarner Losh */
35*ca987d46SWarner Losh
36*ca987d46SWarner Losh #include <sys/param.h>
37*ca987d46SWarner Losh #include <sys/socket.h>
38*ca987d46SWarner Losh #include <string.h>
39*ca987d46SWarner Losh
40*ca987d46SWarner Losh #include <net/if.h>
41*ca987d46SWarner Losh #include <netinet/in.h>
42*ca987d46SWarner Losh #include <netinet/if_ether.h>
43*ca987d46SWarner Losh #include <netinet/in_systm.h>
44*ca987d46SWarner Losh #include <netinet/ip.h>
45*ca987d46SWarner Losh
46*ca987d46SWarner Losh #include "stand.h"
47*ca987d46SWarner Losh #include "net.h"
48*ca987d46SWarner Losh #include "netif.h"
49*ca987d46SWarner Losh
50*ca987d46SWarner Losh /* Caller must leave room for ethernet header in front!! */
51*ca987d46SWarner Losh ssize_t
sendether(struct iodesc * d,void * pkt,size_t len,uint8_t * dea,int etype)52*ca987d46SWarner Losh sendether(struct iodesc *d, void *pkt, size_t len, uint8_t *dea, int etype)
53*ca987d46SWarner Losh {
54*ca987d46SWarner Losh ssize_t n;
55*ca987d46SWarner Losh struct ether_header *eh;
56*ca987d46SWarner Losh
57*ca987d46SWarner Losh #ifdef ETHER_DEBUG
58*ca987d46SWarner Losh if (debug)
59*ca987d46SWarner Losh printf("sendether: called\n");
60*ca987d46SWarner Losh #endif
61*ca987d46SWarner Losh
62*ca987d46SWarner Losh eh = (struct ether_header *)pkt - 1;
63*ca987d46SWarner Losh len += sizeof(*eh);
64*ca987d46SWarner Losh
65*ca987d46SWarner Losh MACPY(d->myea, eh->ether_shost); /* by byte */
66*ca987d46SWarner Losh MACPY(dea, eh->ether_dhost); /* by byte */
67*ca987d46SWarner Losh eh->ether_type = htons(etype);
68*ca987d46SWarner Losh
69*ca987d46SWarner Losh n = netif_put(d, eh, len);
70*ca987d46SWarner Losh if (n == -1 || n < sizeof(*eh))
71*ca987d46SWarner Losh return (-1);
72*ca987d46SWarner Losh
73*ca987d46SWarner Losh n -= sizeof(*eh);
74*ca987d46SWarner Losh return (n);
75*ca987d46SWarner Losh }
76*ca987d46SWarner Losh
77*ca987d46SWarner Losh /*
78*ca987d46SWarner Losh * Get a packet of any Ethernet type, with our address or
79*ca987d46SWarner Losh * the broadcast address. Save the Ether type in etype.
80*ca987d46SWarner Losh * Unless there is an error, we pass the whole packet and the unencapsulated
81*ca987d46SWarner Losh * data.
82*ca987d46SWarner Losh */
83*ca987d46SWarner Losh ssize_t
readether(struct iodesc * d,void ** pkt,void ** payload,time_t tleft,uint16_t * etype)84*ca987d46SWarner Losh readether(struct iodesc *d, void **pkt, void **payload, time_t tleft,
85*ca987d46SWarner Losh uint16_t *etype)
86*ca987d46SWarner Losh {
87*ca987d46SWarner Losh ssize_t n;
88*ca987d46SWarner Losh struct ether_header *eh;
89*ca987d46SWarner Losh void *ptr;
90*ca987d46SWarner Losh
91*ca987d46SWarner Losh #ifdef ETHER_DEBUG
92*ca987d46SWarner Losh if (debug)
93*ca987d46SWarner Losh printf("readether: called\n");
94*ca987d46SWarner Losh #endif
95*ca987d46SWarner Losh
96*ca987d46SWarner Losh ptr = NULL;
97*ca987d46SWarner Losh n = netif_get(d, &ptr, tleft);
98*ca987d46SWarner Losh if (n == -1 || n < sizeof(*eh)) {
99*ca987d46SWarner Losh free(ptr);
100*ca987d46SWarner Losh return (-1);
101*ca987d46SWarner Losh }
102*ca987d46SWarner Losh
103*ca987d46SWarner Losh eh = (struct ether_header *)((uintptr_t)ptr + ETHER_ALIGN);
104*ca987d46SWarner Losh /* Validate Ethernet address. */
105*ca987d46SWarner Losh if (bcmp(d->myea, eh->ether_dhost, 6) != 0 &&
106*ca987d46SWarner Losh bcmp(bcea, eh->ether_dhost, 6) != 0) {
107*ca987d46SWarner Losh #ifdef ETHER_DEBUG
108*ca987d46SWarner Losh if (debug)
109*ca987d46SWarner Losh printf("readether: not ours (ea=%s)\n",
110*ca987d46SWarner Losh ether_sprintf(eh->ether_dhost));
111*ca987d46SWarner Losh #endif
112*ca987d46SWarner Losh free(ptr);
113*ca987d46SWarner Losh return (-1);
114*ca987d46SWarner Losh }
115*ca987d46SWarner Losh
116*ca987d46SWarner Losh *pkt = ptr;
117*ca987d46SWarner Losh *payload = (void *)((uintptr_t)eh + sizeof(*eh));
118*ca987d46SWarner Losh *etype = ntohs(eh->ether_type);
119*ca987d46SWarner Losh
120*ca987d46SWarner Losh n -= sizeof(*eh);
121*ca987d46SWarner Losh return (n);
122*ca987d46SWarner Losh }
123*ca987d46SWarner Losh
124*ca987d46SWarner Losh /*
125*ca987d46SWarner Losh * Convert Ethernet address to printable (loggable) representation.
126*ca987d46SWarner Losh */
127*ca987d46SWarner Losh static char digits[] = "0123456789abcdef";
128*ca987d46SWarner Losh char *
ether_sprintf(u_char * ap)129*ca987d46SWarner Losh ether_sprintf(u_char *ap)
130*ca987d46SWarner Losh {
131*ca987d46SWarner Losh int i;
132*ca987d46SWarner Losh static char etherbuf[18];
133*ca987d46SWarner Losh char *cp = etherbuf;
134*ca987d46SWarner Losh
135*ca987d46SWarner Losh for (i = 0; i < 6; i++) {
136*ca987d46SWarner Losh *cp++ = digits[*ap >> 4];
137*ca987d46SWarner Losh *cp++ = digits[*ap++ & 0xf];
138*ca987d46SWarner Losh *cp++ = ':';
139*ca987d46SWarner Losh }
140*ca987d46SWarner Losh *--cp = 0;
141*ca987d46SWarner Losh return (etherbuf);
142*ca987d46SWarner Losh }
143