View | Details | Raw Unified | Return to bug 277849
Collapse All | Expand All

(-)b/sys/net/if_media.c (-1 / +1 lines)
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

Return to bug 277849