xref: /openbsd-src/sys/netinet/if_ether.h (revision 66570633f456bbd2712f96f3452d64c4aa3115bd)
1*66570633Sbluhm /*	$OpenBSD: if_ether.h,v 1.93 2025/01/01 13:44:22 bluhm Exp $	*/
26a239809Sderaadt /*	$NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5df930be7Sderaadt  * Copyright (c) 1982, 1986, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt  * modification, are permitted provided that the following conditions
10df930be7Sderaadt  * are met:
11df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
1629295d1cSmillert  * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
18df930be7Sderaadt  *    without specific prior written permission.
19df930be7Sderaadt  *
20df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt  * SUCH DAMAGE.
31df930be7Sderaadt  *
32df930be7Sderaadt  *	@(#)if_ether.h	8.1 (Berkeley) 6/10/93
33df930be7Sderaadt  */
34df930be7Sderaadt 
357db87fb0Sangelos #ifndef _NETINET_IF_ETHER_H_
367db87fb0Sangelos #define _NETINET_IF_ETHER_H_
377db87fb0Sangelos 
38df930be7Sderaadt /*
39386aaa9cSbrad  * Some basic Ethernet constants.
40df930be7Sderaadt  */
4180db8022Sfgsch #define	ETHER_ADDR_LEN	6	/* Ethernet address length		*/
4280db8022Sfgsch #define ETHER_TYPE_LEN	2	/* Ethernet type field length		*/
43e4d25771Stodd #define ETHER_CRC_LEN	4	/* Ethernet CRC length			*/
4480db8022Sfgsch #define ETHER_HDR_LEN	((ETHER_ADDR_LEN * 2) + ETHER_TYPE_LEN)
4580db8022Sfgsch #define ETHER_MIN_LEN	64	/* Minimum frame length, CRC included	*/
4680db8022Sfgsch #define ETHER_MAX_LEN	1518	/* Maximum frame length, CRC included	*/
47d51773cbSbrad #define ETHER_MAX_DIX_LEN	1536	/* Maximum DIX frame length	*/
484412f6ecSbrad 
49386aaa9cSbrad /*
50386aaa9cSbrad  * Some Ethernet extensions.
51386aaa9cSbrad  */
524412f6ecSbrad #define ETHER_VLAN_ENCAP_LEN	4	/* len of 802.1Q VLAN encapsulation */
534412f6ecSbrad 
544412f6ecSbrad /*
554412f6ecSbrad  * Mbuf adjust factor to force 32-bit alignment of IP header.
564412f6ecSbrad  * Drivers should do m_adj(m, ETHER_ALIGN) when setting up a
574412f6ecSbrad  * receive so the upper layers get the IP header properly aligned
584412f6ecSbrad  * past the 14-byte Ethernet header.
594412f6ecSbrad  */
604412f6ecSbrad #define ETHER_ALIGN	2	/* driver adjust for IP hdr alignment */
61ba022580Schris 
62ba022580Schris /*
63fc3b235fSreyk  * The maximum supported Ethernet length and some space for encapsulation.
64fc3b235fSreyk  */
65fc3b235fSreyk #define ETHER_MAX_HARDMTU_LEN	65435
66fc3b235fSreyk 
67fc3b235fSreyk /*
68d90fb189Schris  * Ethernet address - 6 octets
69d90fb189Schris  */
70d90fb189Schris struct ether_addr {
71d90fb189Schris 	u_int8_t ether_addr_octet[ETHER_ADDR_LEN];
72d90fb189Schris };
73d90fb189Schris 
74d90fb189Schris /*
75ba022580Schris  * The length of the combined header.
76ba022580Schris  */
77df930be7Sderaadt struct	ether_header {
78df930be7Sderaadt 	u_int8_t  ether_dhost[ETHER_ADDR_LEN];
79df930be7Sderaadt 	u_int8_t  ether_shost[ETHER_ADDR_LEN];
80df930be7Sderaadt 	u_int16_t ether_type;
81df930be7Sderaadt };
82df930be7Sderaadt 
836b938edbSdlg /*
846b938edbSdlg  * VLAN headers.
856b938edbSdlg  */
866b938edbSdlg 
876b938edbSdlg struct  ether_vlan_header {
886b938edbSdlg 	u_char  evl_dhost[ETHER_ADDR_LEN];
896b938edbSdlg 	u_char  evl_shost[ETHER_ADDR_LEN];
906b938edbSdlg 	u_int16_t evl_encap_proto;
916b938edbSdlg 	u_int16_t evl_tag;
926b938edbSdlg 	u_int16_t evl_proto;
936b938edbSdlg };
946b938edbSdlg 
95a1d84234Sdlg #define EVL_VLID_MASK	0xFFF
96a1d84234Sdlg #define EVL_VLID_NULL	0x000
97a1d84234Sdlg /* 0x000 and 0xfff are reserved */
98a1d84234Sdlg #define EVL_VLID_MIN	0x001
99a1d84234Sdlg #define EVL_VLID_MAX	0xFFE
1006b938edbSdlg #define EVL_VLANOFTAG(tag) ((tag) & EVL_VLID_MASK)
1016b938edbSdlg 
1026b938edbSdlg #define EVL_PRIO_MAX    7
1036b938edbSdlg #define EVL_PRIO_BITS   13
1046b938edbSdlg #define EVL_PRIOFTAG(tag) (((tag) >> EVL_PRIO_BITS) & 7)
1056b938edbSdlg 
1066b938edbSdlg #define EVL_ENCAPLEN    4       /* length in octets of encapsulation */
1076b938edbSdlg 
10853fa5dcfSitojun #include <net/ethertypes.h>
109df930be7Sderaadt 
110df930be7Sderaadt #define	ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
11178cd82e3Smpi #define	ETHER_IS_BROADCAST(addr) \
11278cd82e3Smpi 	(((addr)[0] & (addr)[1] & (addr)[2] & \
11378cd82e3Smpi 	  (addr)[3] & (addr)[4] & (addr)[5]) == 0xff)
11478cd82e3Smpi #define	ETHER_IS_ANYADDR(addr)		\
11578cd82e3Smpi 	(((addr)[0] | (addr)[1] | (addr)[2] | \
11678cd82e3Smpi 	  (addr)[3] | (addr)[4] | (addr)[5]) == 0x00)
11778cd82e3Smpi #define	ETHER_IS_EQ(a1, a2)	(memcmp((a1), (a2), ETHER_ADDR_LEN) == 0)
118df930be7Sderaadt 
119cf89a71dSdlg /*
120cf89a71dSdlg  * It can be faster to work with ethernet addresses as a uint64_t.
121cf89a71dSdlg  * Provide some constants and functionality centrally to better
122cf89a71dSdlg  * support this.
123cf89a71dSdlg  */
124cf89a71dSdlg 
125cf89a71dSdlg #define ETH64_IS_MULTICAST(_e64)	((_e64) & 0x010000000000ULL)
126cf89a71dSdlg #define ETH64_IS_BROADCAST(_e64)	((_e64) == 0xffffffffffffULL)
127cf89a71dSdlg #define ETH64_IS_ANYADDR(_e64)		((_e64) == 0x000000000000ULL)
128cf89a71dSdlg 
129cf89a71dSdlg #define ETH64_8021_RSVD_PREFIX		0x0180c2000000ULL
130cf89a71dSdlg #define ETH64_8021_RSVD_MASK		0xfffffffffff0ULL
131cf89a71dSdlg #define ETH64_IS_8021_RSVD(_e64)	\
132cf89a71dSdlg     (((_e64) & ETH64_8021_RSVD_MASK) == ETH64_8021_RSVD_PREFIX)
133cf89a71dSdlg 
134cf89a71dSdlg /*
135cf89a71dSdlg  * Ethernet MTU constants.
136cf89a71dSdlg  */
13780db8022Sfgsch #define	ETHERMTU	(ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
13880db8022Sfgsch #define	ETHERMIN	(ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
139df930be7Sderaadt 
140cc403c85Snate /*
141678831beSjsg  * Ethernet CRC32 polynomials (big- and little-endian versions).
142cc403c85Snate  */
143cc403c85Snate #define	ETHER_CRC_POLY_LE	0xedb88320
144cc403c85Snate #define	ETHER_CRC_POLY_BE	0x04c11db6
145cc403c85Snate 
14696dc0726Smpi /*
14796dc0726Smpi  * Ethernet Address Resolution Protocol.
14896dc0726Smpi  *
14996dc0726Smpi  * See RFC 826 for protocol description.  Structure below is adapted
15096dc0726Smpi  * to resolving internet addresses.  Field names used correspond to
15196dc0726Smpi  * RFC 826.
15296dc0726Smpi  */
15396dc0726Smpi struct	ether_arp {
15496dc0726Smpi 	struct	 arphdr ea_hdr;			/* fixed-size header */
15596dc0726Smpi 	u_int8_t arp_sha[ETHER_ADDR_LEN];	/* sender hardware address */
15696dc0726Smpi 	u_int8_t arp_spa[4];			/* sender protocol address */
15796dc0726Smpi 	u_int8_t arp_tha[ETHER_ADDR_LEN];	/* target hardware address */
15896dc0726Smpi 	u_int8_t arp_tpa[4];			/* target protocol address */
15996dc0726Smpi };
16096dc0726Smpi #define	arp_hrd	ea_hdr.ar_hrd
16196dc0726Smpi #define	arp_pro	ea_hdr.ar_pro
16296dc0726Smpi #define	arp_hln	ea_hdr.ar_hln
16396dc0726Smpi #define	arp_pln	ea_hdr.ar_pln
16496dc0726Smpi #define	arp_op	ea_hdr.ar_op
16596dc0726Smpi 
16696dc0726Smpi struct sockaddr_inarp {
16796dc0726Smpi 	u_int8_t  sin_len;
16896dc0726Smpi 	u_int8_t  sin_family;
16996dc0726Smpi 	u_int16_t sin_port;
17096dc0726Smpi 	struct	  in_addr sin_addr;
17196dc0726Smpi 	struct	  in_addr sin_srcaddr;
17296dc0726Smpi 	u_int16_t sin_tos;
17396dc0726Smpi 	u_int16_t sin_other;
17496dc0726Smpi #define SIN_PROXY 1
17596dc0726Smpi };
17696dc0726Smpi 
17796dc0726Smpi /*
17896dc0726Smpi  * IP and ethernet specific routing flags
17996dc0726Smpi  */
18096dc0726Smpi #define	RTF_USETRAILERS	  RTF_PROTO1	/* use trailers */
18196dc0726Smpi #define	RTF_PERMANENT_ARP RTF_PROTO3    /* only manual overwrite of entry */
18296dc0726Smpi 
183df930be7Sderaadt #ifdef _KERNEL
18469761fb1Skn 
18569761fb1Skn #include <sys/refcnt.h>
18669761fb1Skn 
187df930be7Sderaadt /*
188df930be7Sderaadt  * Macro to map an IP multicast address to an Ethernet multicast address.
189df930be7Sderaadt  * The high-order 25 bits of the Ethernet address are statically assigned,
190df930be7Sderaadt  * and the low-order 23 bits are taken from the low end of the IP address.
191df930be7Sderaadt  */
192df930be7Sderaadt #define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr)				\
193df930be7Sderaadt 	/* struct in_addr *ipaddr; */					\
194df930be7Sderaadt 	/* u_int8_t enaddr[ETHER_ADDR_LEN]; */				\
19592df2d4eSdlg do {									\
196df930be7Sderaadt 	(enaddr)[0] = 0x01;						\
197df930be7Sderaadt 	(enaddr)[1] = 0x00;						\
198df930be7Sderaadt 	(enaddr)[2] = 0x5e;						\
199df930be7Sderaadt 	(enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f;			\
200df930be7Sderaadt 	(enaddr)[4] = ((u_int8_t *)ipaddr)[2];				\
201df930be7Sderaadt 	(enaddr)[5] = ((u_int8_t *)ipaddr)[3];				\
20292df2d4eSdlg } while (/* CONSTCOND */ 0)
203287546eaSitojun 
204287546eaSitojun /*
205287546eaSitojun  * Macro to map an IPv6 multicast address to an Ethernet multicast address.
206287546eaSitojun  * The high-order 16 bits of the Ethernet address are statically assigned,
207287546eaSitojun  * and the low-order 32 bits are taken from the low end of the IPv6 address.
208287546eaSitojun  */
209287546eaSitojun #define ETHER_MAP_IPV6_MULTICAST(ip6addr, enaddr)			\
210287546eaSitojun 	/* struct in6_addr *ip6addr; */					\
211287546eaSitojun 	/* u_int8_t enaddr[ETHER_ADDR_LEN]; */				\
21292df2d4eSdlg do {									\
213287546eaSitojun 	(enaddr)[0] = 0x33;						\
214287546eaSitojun 	(enaddr)[1] = 0x33;						\
215287546eaSitojun 	(enaddr)[2] = ((u_int8_t *)ip6addr)[12];			\
216287546eaSitojun 	(enaddr)[3] = ((u_int8_t *)ip6addr)[13];			\
217287546eaSitojun 	(enaddr)[4] = ((u_int8_t *)ip6addr)[14];			\
218287546eaSitojun 	(enaddr)[5] = ((u_int8_t *)ip6addr)[15];			\
21992df2d4eSdlg } while (/* CONSTCOND */ 0)
220a7ae9819Sderaadt 
2210deb6685Smpi #include <net/if_var.h>	/* for "struct ifnet" */
2220deb6685Smpi 
223d79d7022Sdlg struct ether_brport {
2244e0e7160Sdlg 	struct mbuf	*(*eb_input)(struct ifnet *, struct mbuf *,
2254e0e7160Sdlg 			   uint64_t, void *);
226baf71576Ssashan 	void		(*eb_port_take)(void *);
227baf71576Ssashan 	void		(*eb_port_rele)(void *);
228d79d7022Sdlg 	void		  *eb_port;
229d79d7022Sdlg };
230d79d7022Sdlg 
231df930be7Sderaadt /*
232df930be7Sderaadt  * Structure shared between the ethernet driver modules and
233df930be7Sderaadt  * the address resolution code.  For example, each ec_softc or il_softc
234df930be7Sderaadt  * begins with this structure.
235df930be7Sderaadt  */
236df930be7Sderaadt struct	arpcom {
237df930be7Sderaadt 	struct	 ifnet ac_if;			/* network-visible interface */
238df930be7Sderaadt 	u_int8_t ac_enaddr[ETHER_ADDR_LEN];	/* ethernet hardware address */
239db36d367Sderaadt 	char	 ac__pad[2];			/* pad for some machines */
2404ccfd590Sdlg 	LIST_HEAD(, ether_multi) ac_multiaddrs;	/* list of multicast addrs */
2414ccfd590Sdlg 	int	 ac_multicnt;			/* length of ac_multiaddrs */
2424ccfd590Sdlg 	int	 ac_multirangecnt;		/* number of mcast ranges */
2434ccfd590Sdlg 
2448edbca89Sdlg 	void	*ac_trunkport;
245d79d7022Sdlg 	const struct ether_brport *ac_brport;
246df930be7Sderaadt };
247df930be7Sderaadt 
2484faff50fSchris extern int arpt_keep;				/* arp resolved cache expire */
2494faff50fSchris extern int arpt_down;				/* arp down cache expire */
2504faff50fSchris 
2514c366c49Smiod extern u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN];
2526ff0435bSstsp extern u_int8_t etheranyaddr[ETHER_ADDR_LEN];
2534c366c49Smiod extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
2544c366c49Smiod extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
255df930be7Sderaadt 
256f97093e3Smpi #ifdef NFSCLIENT
257f97093e3Smpi extern unsigned int revarp_ifidx;
258f97093e3Smpi #endif /* NFSCLIENT */
259f97093e3Smpi 
2605a411d3cSmpi void	revarpinput(struct ifnet *, struct mbuf *);
261f97093e3Smpi void	revarprequest(struct ifnet *);
262f97093e3Smpi int	revarpwhoarewe(struct ifnet *, struct in_addr *, struct in_addr *);
263f97093e3Smpi int	revarpwhoami(struct in_addr *, struct ifnet *);
264f97093e3Smpi 
265632220b1Sbluhm void	arpinit(void);
2665a411d3cSmpi void	arpinput(struct ifnet *, struct mbuf *);
267f97093e3Smpi void	arprequest(struct ifnet *, u_int32_t *, u_int32_t *, u_int8_t *);
268c4071fd1Smillert void	arpwhohas(struct arpcom *, struct in_addr *);
269f97093e3Smpi int	arpproxy(struct in_addr, unsigned int);
27096dc0726Smpi int	arpresolve(struct ifnet *, struct rtentry *, struct mbuf *,
27196dc0726Smpi 	    struct sockaddr *, u_char *);
272dcb17c31Smpi void	arp_rtrequest(struct ifnet *, int, struct rtentry *);
273df930be7Sderaadt 
27496dc0726Smpi void	ether_fakeaddr(struct ifnet *);
275c4071fd1Smillert int	ether_addmulti(struct ifreq *, struct arpcom *);
276c4071fd1Smillert int	ether_delmulti(struct ifreq *, struct arpcom *);
27704cdc2f2Spatrick int	ether_multiaddr(struct sockaddr *, u_int8_t *, u_int8_t *);
278f0fcdf5cSmpi void	ether_ifattach(struct ifnet *);
279f0fcdf5cSmpi void	ether_ifdetach(struct ifnet *);
280f0fcdf5cSmpi int	ether_ioctl(struct ifnet *, struct arpcom *, u_long, caddr_t);
28123293512Sdlg void	ether_input(struct ifnet *, struct mbuf *);
28232303230Sdlg int	ether_resolve(struct ifnet *, struct mbuf *, struct sockaddr *,
28332303230Sdlg 	    struct rtentry *, struct ether_header *);
28432303230Sdlg struct mbuf *
28532303230Sdlg 	ether_encap(struct ifnet *, struct mbuf *, struct sockaddr *,
28632303230Sdlg 	    struct rtentry *, int *);
28732303230Sdlg int	ether_output(struct ifnet *, struct mbuf *, struct sockaddr *,
28832303230Sdlg 	    struct rtentry *);
289f0fcdf5cSmpi void	ether_rtrequest(struct ifnet *, int, struct rtentry *);
290f0fcdf5cSmpi char	*ether_sprintf(u_char *);
291f0fcdf5cSmpi 
292d79d7022Sdlg int	ether_brport_isset(struct ifnet *);
293d79d7022Sdlg void	ether_brport_set(struct ifnet *, const struct ether_brport *);
294d79d7022Sdlg void	ether_brport_clr(struct ifnet *);
295d79d7022Sdlg const struct ether_brport *
296d79d7022Sdlg 	ether_brport_get(struct ifnet *);
297d79d7022Sdlg const struct ether_brport *
298d79d7022Sdlg 	ether_brport_get_locked(struct ifnet *);
299df930be7Sderaadt 
300cf89a71dSdlg uint64_t	ether_addr_to_e64(const struct ether_addr *);
301cf89a71dSdlg void		ether_e64_to_addr(struct ether_addr *, uint64_t);
302cf89a71dSdlg 
30326fd91ceSjan struct ether_extracted {
30426fd91ceSjan 	struct ether_header		*eh;
305d1dd6743Sjan 	struct ether_vlan_header	*evh;
30626fd91ceSjan 	struct ip			*ip4;
30726fd91ceSjan 	struct ip6_hdr			*ip6;
30826fd91ceSjan 	struct tcphdr			*tcp;
30926fd91ceSjan 	struct udphdr			*udp;
310ac5f541aSbluhm 	u_int				 iplen;
311ac5f541aSbluhm 	u_int				 iphlen;
312e78a66e5Sbluhm 	u_int				 tcphlen;
313e78a66e5Sbluhm 	u_int				 paylen;
31426fd91ceSjan };
31526fd91ceSjan 
31626fd91ceSjan void ether_extract_headers(struct mbuf *, struct ether_extracted *);
31726fd91ceSjan 
318df930be7Sderaadt /*
319df930be7Sderaadt  * Ethernet multicast address structure.  There is one of these for each
320df930be7Sderaadt  * multicast address or range of multicast addresses that we are supposed
321df930be7Sderaadt  * to listen to on a particular interface.  They are kept in a linked list,
322df930be7Sderaadt  * rooted in the interface's arpcom structure.  (This really has nothing to
323df930be7Sderaadt  * do with ARP, or with the Internet address family, but this appears to be
324df930be7Sderaadt  * the minimally-disrupting place to put it.)
325df930be7Sderaadt  */
326df930be7Sderaadt struct ether_multi {
327df930be7Sderaadt 	u_int8_t enm_addrlo[ETHER_ADDR_LEN]; /* low  or only address of range */
328df930be7Sderaadt 	u_int8_t enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */
32969761fb1Skn 	struct refcnt enm_refcnt;		/* no. claims to this addr/range */
330df930be7Sderaadt 	LIST_ENTRY(ether_multi) enm_list;
331df930be7Sderaadt };
332df930be7Sderaadt 
333df930be7Sderaadt /*
334df930be7Sderaadt  * Structure used by macros below to remember position when stepping through
335df930be7Sderaadt  * all of the ether_multi records.
336df930be7Sderaadt  */
337df930be7Sderaadt struct ether_multistep {
338df930be7Sderaadt 	struct ether_multi  *e_enm;
339df930be7Sderaadt };
340df930be7Sderaadt 
341df930be7Sderaadt /*
342df930be7Sderaadt  * Macro for looking up the ether_multi record for a given range of Ethernet
343df930be7Sderaadt  * multicast addresses connected to a given arpcom structure.  If no matching
344df930be7Sderaadt  * record is found, "enm" returns NULL.
345df930be7Sderaadt  */
346df930be7Sderaadt #define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm)			\
347df930be7Sderaadt 	/* u_int8_t addrlo[ETHER_ADDR_LEN]; */				\
348df930be7Sderaadt 	/* u_int8_t addrhi[ETHER_ADDR_LEN]; */				\
349df930be7Sderaadt 	/* struct arpcom *ac; */					\
350df930be7Sderaadt 	/* struct ether_multi *enm; */					\
35192df2d4eSdlg do {									\
3521573508eSmiod 	for ((enm) = LIST_FIRST(&(ac)->ac_multiaddrs);			\
35366c84f52Stedu 	    (enm) != NULL &&						\
354f8575965Stedu 	    (memcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 ||\
355f8575965Stedu 	     memcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0);	\
3561573508eSmiod 		(enm) = LIST_NEXT((enm), enm_list));			\
35792df2d4eSdlg } while (/* CONSTCOND */ 0)
358df930be7Sderaadt 
359df930be7Sderaadt /*
360df930be7Sderaadt  * Macro to step through all of the ether_multi records, one at a time.
361df930be7Sderaadt  * The current position is remembered in "step", which the caller must
362df930be7Sderaadt  * provide.  ETHER_FIRST_MULTI(), below, must be called to initialize "step"
363df930be7Sderaadt  * and get the first record.  Both macros return a NULL "enm" when there
364df930be7Sderaadt  * are no remaining records.
365df930be7Sderaadt  */
366df930be7Sderaadt #define ETHER_NEXT_MULTI(step, enm)					\
367df930be7Sderaadt 	/* struct ether_multistep step; */				\
368df930be7Sderaadt 	/* struct ether_multi *enm; */					\
36992df2d4eSdlg do {									\
370df930be7Sderaadt 	if (((enm) = (step).e_enm) != NULL)				\
3711573508eSmiod 		(step).e_enm = LIST_NEXT((enm), enm_list);		\
37292df2d4eSdlg } while (/* CONSTCOND */ 0)
373df930be7Sderaadt 
374df930be7Sderaadt #define ETHER_FIRST_MULTI(step, ac, enm)				\
375df930be7Sderaadt 	/* struct ether_multistep step; */				\
376df930be7Sderaadt 	/* struct arpcom *ac; */					\
377df930be7Sderaadt 	/* struct ether_multi *enm; */					\
37892df2d4eSdlg do {									\
3791573508eSmiod 	(step).e_enm = LIST_FIRST(&(ac)->ac_multiaddrs);		\
380df930be7Sderaadt 	ETHER_NEXT_MULTI((step), (enm));				\
38192df2d4eSdlg } while (/* CONSTCOND */ 0)
382b400e158Sniklas 
3830849d918Sdjm u_int32_t ether_crc32_le_update(u_int32_t crc, const u_int8_t *, size_t);
3840849d918Sdjm u_int32_t ether_crc32_be_update(u_int32_t crc, const u_int8_t *, size_t);
385cc403c85Snate u_int32_t ether_crc32_le(const u_int8_t *, size_t);
386cc403c85Snate u_int32_t ether_crc32_be(const u_int8_t *, size_t);
387cc403c85Snate 
38896dc0726Smpi #else /* _KERNEL */
389ceeee157Sderaadt 
3905c86c1acSnaddy __BEGIN_DECLS
391c4071fd1Smillert char *ether_ntoa(struct ether_addr *);
3929f33d8a6Stedu struct ether_addr *ether_aton(const char *);
393c4071fd1Smillert int ether_ntohost(char *, struct ether_addr *);
3949f33d8a6Stedu int ether_hostton(const char *, struct ether_addr *);
3959f33d8a6Stedu int ether_line(const char *, struct ether_addr *, char *);
3965c86c1acSnaddy __END_DECLS
397ceeee157Sderaadt 
3987db87fb0Sangelos #endif /* _KERNEL */
3997db87fb0Sangelos #endif /* _NETINET_IF_ETHER_H_ */
400