Lines 182-380
ifmedia_set(struct ifmedia *ifm, int target)
Link Here
|
182 |
ifmedia_printword(ifm->ifm_cur->ifm_media); |
182 |
ifmedia_printword(ifm->ifm_cur->ifm_media); |
183 |
} |
183 |
} |
184 |
#endif |
184 |
#endif |
185 |
} |
185 |
} |
186 |
|
186 |
|
187 |
/* |
187 |
/* |
188 |
* Given a media word, return one suitable for an application |
188 |
* Given a media word, return one suitable for an application |
189 |
* using the original encoding. |
189 |
* using the original encoding. |
190 |
*/ |
190 |
*/ |
191 |
static int |
191 |
static int |
192 |
compat_media(int media) |
192 |
compat_media(int media) |
193 |
{ |
193 |
{ |
194 |
|
194 |
|
195 |
if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) { |
195 |
if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) { |
196 |
media &= ~(IFM_ETH_XTYPE|IFM_TMASK); |
196 |
media &= ~(IFM_ETH_XTYPE|IFM_TMASK); |
197 |
media |= IFM_OTHER; |
197 |
media |= IFM_OTHER; |
198 |
} |
198 |
} |
199 |
return (media); |
199 |
return (media); |
200 |
} |
200 |
} |
201 |
|
201 |
|
202 |
/* |
202 |
/* |
203 |
* Device-independent media ioctl support function. |
203 |
* Device-independent media ioctl support function. |
204 |
*/ |
204 |
*/ |
205 |
int |
205 |
int |
206 |
ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, struct ifmedia *ifm, |
206 |
ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, struct ifmedia *ifm, |
207 |
u_long cmd) |
207 |
u_long cmd) |
208 |
{ |
208 |
{ |
209 |
struct ifmedia_entry *match; |
209 |
struct ifmedia_entry *match; |
210 |
struct ifmediareq *ifmr = (struct ifmediareq *) ifr; |
210 |
struct ifmediareq *ifmr = (struct ifmediareq *) ifr; |
211 |
int error = 0; |
211 |
int error = 0; |
212 |
|
212 |
|
213 |
if (ifp == NULL || ifr == NULL || ifm == NULL) |
213 |
if (ifp == NULL || ifr == NULL || ifm == NULL) |
214 |
return (EINVAL); |
214 |
return (EINVAL); |
215 |
|
215 |
|
216 |
switch (cmd) { |
216 |
switch (cmd) { |
217 |
/* |
217 |
/* |
218 |
* Set the current media. |
218 |
* Set the current media. |
219 |
*/ |
219 |
*/ |
220 |
case SIOCSIFMEDIA: |
220 |
case SIOCSIFMEDIA: |
221 |
{ |
221 |
{ |
222 |
struct ifmedia_entry *oldentry; |
222 |
struct ifmedia_entry *oldentry; |
223 |
int oldmedia; |
223 |
int oldmedia; |
224 |
int newmedia = ifr->ifr_media; |
224 |
int newmedia = ifr->ifr_media; |
225 |
|
225 |
|
226 |
match = ifmedia_match(ifm, newmedia, ifm->ifm_mask); |
226 |
match = ifmedia_match(ifm, newmedia, ifm->ifm_mask); |
227 |
if (match == NULL) { |
227 |
if (match == NULL) { |
228 |
#ifdef IFMEDIA_DEBUG |
228 |
#ifdef IFMEDIA_DEBUG |
229 |
if (ifmedia_debug) { |
229 |
if (ifmedia_debug) { |
230 |
printf( |
230 |
printf( |
231 |
"ifmedia_ioctl: no media found for %#010x mask %#010x\n", |
231 |
"ifmedia_ioctl: no media found for %#010x mask %#010x\n", |
232 |
newmedia, ifm->ifm_mask); |
232 |
newmedia, ifm->ifm_mask); |
233 |
} |
233 |
} |
234 |
#endif |
234 |
#endif |
235 |
return (ENXIO); |
235 |
return (ENXIO); |
236 |
} |
236 |
} |
237 |
|
237 |
|
238 |
/* |
238 |
/* |
239 |
* If no change, we're done. |
239 |
* If no change, we're done. |
240 |
* XXX Automedia may invole software intervention. |
240 |
* XXX Automedia may invole software intervention. |
241 |
* Keep going in case the connected media changed. |
241 |
* Keep going in case the connected media changed. |
242 |
* Similarly, if best match changed (kernel debugger?). |
242 |
* Similarly, if best match changed (kernel debugger?). |
243 |
*/ |
243 |
*/ |
244 |
if (IFM_SUBTYPE(newmedia) != IFM_AUTO && |
244 |
if (IFM_SUBTYPE(newmedia) != IFM_AUTO && |
245 |
newmedia == ifm->ifm_media && match == ifm->ifm_cur) |
245 |
newmedia == ifm->ifm_media && match == ifm->ifm_cur) |
246 |
return (0); |
246 |
return (0); |
247 |
|
247 |
|
248 |
/* |
248 |
/* |
249 |
* We found a match, now make the driver switch to it. |
249 |
* We found a match, now make the driver switch to it. |
250 |
* Make sure to preserve our old media type in case the |
250 |
* Make sure to preserve our old media type in case the |
251 |
* driver can't switch. |
251 |
* driver can't switch. |
252 |
*/ |
252 |
*/ |
253 |
#ifdef IFMEDIA_DEBUG |
253 |
#ifdef IFMEDIA_DEBUG |
254 |
if (ifmedia_debug) { |
254 |
if (ifmedia_debug) { |
255 |
printf("ifmedia_ioctl: switching %s to ", |
255 |
printf("ifmedia_ioctl: switching %s to ", |
256 |
ifp->if_xname); |
256 |
ifp->if_xname); |
257 |
ifmedia_printword(match->ifm_media); |
257 |
ifmedia_printword(match->ifm_media); |
258 |
} |
258 |
} |
259 |
#endif |
259 |
#endif |
260 |
oldentry = ifm->ifm_cur; |
260 |
oldentry = ifm->ifm_cur; |
261 |
oldmedia = ifm->ifm_media; |
261 |
oldmedia = ifm->ifm_media; |
262 |
ifm->ifm_cur = match; |
262 |
ifm->ifm_cur = match; |
263 |
ifm->ifm_media = newmedia; |
263 |
ifm->ifm_media = newmedia; |
264 |
error = (*ifm->ifm_change)(ifp); |
264 |
error = (*ifm->ifm_change)(ifp); |
265 |
if (error) { |
265 |
if (error) { |
266 |
ifm->ifm_cur = oldentry; |
266 |
ifm->ifm_cur = oldentry; |
267 |
ifm->ifm_media = oldmedia; |
267 |
ifm->ifm_media = oldmedia; |
268 |
} |
268 |
} |
269 |
break; |
269 |
break; |
270 |
} |
270 |
} |
271 |
|
271 |
|
272 |
/* |
272 |
/* |
273 |
* Get list of available media and current media on interface. |
273 |
* Get list of available media and current media on interface. |
274 |
*/ |
274 |
*/ |
275 |
case SIOCGIFMEDIA: |
275 |
case SIOCGIFMEDIA: |
276 |
case SIOCGIFXMEDIA: |
276 |
case SIOCGIFXMEDIA: |
277 |
{ |
277 |
{ |
278 |
struct ifmedia_entry *ep; |
278 |
struct ifmedia_entry *ep; |
279 |
int i; |
279 |
int i; |
280 |
|
280 |
|
281 |
if (ifmr->ifm_count < 0) |
281 |
if (ifmr->ifm_count < 0 || ifm->ifm_status == NULL) |
282 |
return (EINVAL); |
282 |
return (EINVAL); |
283 |
|
283 |
|
284 |
if (cmd == SIOCGIFMEDIA) { |
284 |
if (cmd == SIOCGIFMEDIA) { |
285 |
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? |
285 |
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? |
286 |
compat_media(ifm->ifm_cur->ifm_media) : IFM_NONE; |
286 |
compat_media(ifm->ifm_cur->ifm_media) : IFM_NONE; |
287 |
} else { |
287 |
} else { |
288 |
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? |
288 |
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? |
289 |
ifm->ifm_cur->ifm_media : IFM_NONE; |
289 |
ifm->ifm_cur->ifm_media : IFM_NONE; |
290 |
} |
290 |
} |
291 |
ifmr->ifm_mask = ifm->ifm_mask; |
291 |
ifmr->ifm_mask = ifm->ifm_mask; |
292 |
ifmr->ifm_status = 0; |
292 |
ifmr->ifm_status = 0; |
293 |
(*ifm->ifm_status)(ifp, ifmr); |
293 |
(*ifm->ifm_status)(ifp, ifmr); |
294 |
|
294 |
|
295 |
/* |
295 |
/* |
296 |
* If there are more interfaces on the list, count |
296 |
* If there are more interfaces on the list, count |
297 |
* them. This allows the caller to set ifmr->ifm_count |
297 |
* them. This allows the caller to set ifmr->ifm_count |
298 |
* to 0 on the first call to know how much space to |
298 |
* to 0 on the first call to know how much space to |
299 |
* allocate. |
299 |
* allocate. |
300 |
*/ |
300 |
*/ |
301 |
i = 0; |
301 |
i = 0; |
302 |
LIST_FOREACH(ep, &ifm->ifm_list, ifm_list) { |
302 |
LIST_FOREACH(ep, &ifm->ifm_list, ifm_list) { |
303 |
if (i < ifmr->ifm_count) { |
303 |
if (i < ifmr->ifm_count) { |
304 |
error = copyout(&ep->ifm_media, |
304 |
error = copyout(&ep->ifm_media, |
305 |
ifmr->ifm_ulist + i, sizeof(int)); |
305 |
ifmr->ifm_ulist + i, sizeof(int)); |
306 |
if (error != 0) |
306 |
if (error != 0) |
307 |
break; |
307 |
break; |
308 |
} |
308 |
} |
309 |
i++; |
309 |
i++; |
310 |
} |
310 |
} |
311 |
if (error == 0 && i > ifmr->ifm_count) |
311 |
if (error == 0 && i > ifmr->ifm_count) |
312 |
error = ifmr->ifm_count != 0 ? E2BIG : 0; |
312 |
error = ifmr->ifm_count != 0 ? E2BIG : 0; |
313 |
ifmr->ifm_count = i; |
313 |
ifmr->ifm_count = i; |
314 |
break; |
314 |
break; |
315 |
} |
315 |
} |
316 |
|
316 |
|
317 |
default: |
317 |
default: |
318 |
return (EINVAL); |
318 |
return (EINVAL); |
319 |
} |
319 |
} |
320 |
|
320 |
|
321 |
return (error); |
321 |
return (error); |
322 |
} |
322 |
} |
323 |
|
323 |
|
324 |
/* |
324 |
/* |
325 |
* Find media entry matching a given ifm word. |
325 |
* Find media entry matching a given ifm word. |
326 |
* |
326 |
* |
327 |
*/ |
327 |
*/ |
328 |
static struct ifmedia_entry * |
328 |
static struct ifmedia_entry * |
329 |
ifmedia_match(struct ifmedia *ifm, int target, int mask) |
329 |
ifmedia_match(struct ifmedia *ifm, int target, int mask) |
330 |
{ |
330 |
{ |
331 |
struct ifmedia_entry *match, *next; |
331 |
struct ifmedia_entry *match, *next; |
332 |
|
332 |
|
333 |
match = NULL; |
333 |
match = NULL; |
334 |
mask = ~mask; |
334 |
mask = ~mask; |
335 |
|
335 |
|
336 |
LIST_FOREACH(next, &ifm->ifm_list, ifm_list) { |
336 |
LIST_FOREACH(next, &ifm->ifm_list, ifm_list) { |
337 |
if ((next->ifm_media & mask) == (target & mask)) { |
337 |
if ((next->ifm_media & mask) == (target & mask)) { |
338 |
#if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC) |
338 |
#if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC) |
339 |
if (match) { |
339 |
if (match) { |
340 |
printf("ifmedia_match: multiple match for " |
340 |
printf("ifmedia_match: multiple match for " |
341 |
"%#010x/%#010x\n", target, mask); |
341 |
"%#010x/%#010x\n", target, mask); |
342 |
} |
342 |
} |
343 |
#endif |
343 |
#endif |
344 |
match = next; |
344 |
match = next; |
345 |
} |
345 |
} |
346 |
} |
346 |
} |
347 |
|
347 |
|
348 |
return (match); |
348 |
return (match); |
349 |
} |
349 |
} |
350 |
|
350 |
|
351 |
/* |
351 |
/* |
352 |
* Compute the interface `baudrate' from the media, for the interface |
352 |
* Compute the interface `baudrate' from the media, for the interface |
353 |
* metrics (used by routing daemons). |
353 |
* metrics (used by routing daemons). |
354 |
*/ |
354 |
*/ |
355 |
static const struct ifmedia_baudrate ifmedia_baudrate_descriptions[] = |
355 |
static const struct ifmedia_baudrate ifmedia_baudrate_descriptions[] = |
356 |
IFM_BAUDRATE_DESCRIPTIONS; |
356 |
IFM_BAUDRATE_DESCRIPTIONS; |
357 |
|
357 |
|
358 |
uint64_t |
358 |
uint64_t |
359 |
ifmedia_baudrate(int mword) |
359 |
ifmedia_baudrate(int mword) |
360 |
{ |
360 |
{ |
361 |
int i; |
361 |
int i; |
362 |
|
362 |
|
363 |
for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) { |
363 |
for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) { |
364 |
if (IFM_TYPE_MATCH(mword, ifmedia_baudrate_descriptions[i]. |
364 |
if (IFM_TYPE_MATCH(mword, ifmedia_baudrate_descriptions[i]. |
365 |
ifmb_word)) |
365 |
ifmb_word)) |
366 |
return (ifmedia_baudrate_descriptions[i].ifmb_baudrate); |
366 |
return (ifmedia_baudrate_descriptions[i].ifmb_baudrate); |
367 |
} |
367 |
} |
368 |
|
368 |
|
369 |
/* Not known. */ |
369 |
/* Not known. */ |
370 |
return (0); |
370 |
return (0); |
371 |
} |
371 |
} |
372 |
|
372 |
|
373 |
#ifdef IFMEDIA_DEBUG |
373 |
#ifdef IFMEDIA_DEBUG |
374 |
static const struct ifmedia_description ifm_type_descriptions[] = |
374 |
static const struct ifmedia_description ifm_type_descriptions[] = |
375 |
IFM_TYPE_DESCRIPTIONS; |
375 |
IFM_TYPE_DESCRIPTIONS; |
376 |
|
376 |
|
377 |
static const struct ifmedia_description ifm_subtype_ethernet_descriptions[] = |
377 |
static const struct ifmedia_description ifm_subtype_ethernet_descriptions[] = |
378 |
IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; |
378 |
IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; |
379 |
|
379 |
|
380 |
static const struct ifmedia_description |
380 |
static const struct ifmedia_description |