1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/kernel.h>
61#include <sys/malloc.h>
62#include <sys/mbuf.h>
63#include <sys/socket.h>
64#include <sys/sockio.h>
65#include <sys/sysctl.h>
66
67#include <net/if.h>
68#include <net/route.h>
69#include <net/if_llc.h>
70#include <net/if_dl.h>
71#include <net/if_types.h>
72
73#if INET || INET6
74#include <netinet/in.h>
75#include <netinet/in_var.h>
76#include <netinet/if_ether.h>
77#include <netinet/in_systm.h>
78#include <netinet/ip.h>
79#endif
80
81#if IPX
82#include <netipx/ipx.h>
83#include <netipx/ipx_if.h>
84#endif
85
86#include <sys/socketvar.h>
87
88#if LLC && CCITT
89extern struct ifqueue pkintrq;
90#endif
91
92#if BRIDGE
93#include <net/bridge.h>
94#endif
95
96
97#if NVLAN > 0
98#include <net/if_vlan_var.h>
99#endif
100
101extern u_char etherbroadcastaddr[];
102#define senderr(e) do { error = (e); goto bad;} while (0)
103
104
105
106
107
108int
109ether_resolvemulti(
110 struct ifnet *ifp,
111 struct sockaddr **llsa,
112 struct sockaddr *sa)
113{
114 struct sockaddr_dl *sdl;
115 struct sockaddr_in *sin;
116 u_char *e_addr;
117#if INET6
118 struct sockaddr_in6 *sin6;
119#endif
120
121
122 switch(sa->sa_family) {
123 case AF_UNSPEC:
124
125
126
127 e_addr = &sa->sa_data[0];
128 if ((e_addr[0] & 1) != 1)
129 return EADDRNOTAVAIL;
130 *llsa = 0;
131 return 0;
132
133 case AF_LINK:
134
135
136
137 sdl = (struct sockaddr_dl *)sa;
138 e_addr = LLADDR(sdl);
139 if ((e_addr[0] & 1) != 1)
140 return EADDRNOTAVAIL;
141 *llsa = 0;
142 return 0;
143
144#if INET
145 case AF_INET:
146 sin = (struct sockaddr_in *)sa;
147 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
148 return EADDRNOTAVAIL;
149 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
150 M_WAITOK);
151 sdl->sdl_len = sizeof *sdl;
152 sdl->sdl_family = AF_LINK;
153 sdl->sdl_index = ifp->if_index;
154 sdl->sdl_type = IFT_ETHER;
155 sdl->sdl_nlen = 0;
156 sdl->sdl_alen = ETHER_ADDR_LEN;
157 sdl->sdl_slen = 0;
158 e_addr = LLADDR(sdl);
159 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
160 *llsa = (struct sockaddr *)sdl;
161 return 0;
162#endif
163#if INET6
164 case AF_INET6:
165 sin6 = (struct sockaddr_in6 *)sa;
166 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
167
168
169
170
171
172 ifp->if_flags |= IFF_ALLMULTI;
173 *llsa = 0;
174 return 0;
175 }
176 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
177 M_WAITOK);
178 sdl->sdl_len = sizeof *sdl;
179 sdl->sdl_family = AF_LINK;
180 sdl->sdl_index = ifp->if_index;
181 sdl->sdl_type = IFT_ETHER;
182 sdl->sdl_nlen = 0;
183 sdl->sdl_alen = ETHER_ADDR_LEN;
184 sdl->sdl_slen = 0;
185 e_addr = LLADDR(sdl);
186 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
187 kprintf("ether_resolvemulti Adding %x:%x:%x:%x:%x:%x\n",
188 e_addr[0], e_addr[1], e_addr[2], e_addr[3], e_addr[4], e_addr[5]);
189 *llsa = (struct sockaddr *)sdl;
190 return 0;
191#endif
192
193 default:
194
195
196
197
198 return EAFNOSUPPORT;
199 }
200}
201
202
203
204
205
206static u_char digits[] = "0123456789abcdef";
207char *
208ether_sprintf(p, ap)
209 register u_char *p;
210 register u_char *ap;
211{ register char *cp;
212 register i;
213
214 for (cp = p, i = 0; i < 6; i++) {
215 *cp++ = digits[*ap >> 4];
216 *cp++ = digits[*ap++ & 0xf];
217 *cp++ = ':';
218 }
219 *--cp = 0;
220 return (p);
221}
222