tap7.diff

naoya.sugioka, 05/06/2009 12:38 AM

Download (7.58 KB)

View differences:

sys/net/tap/if_tap.c
65 65
#include <net/if.h>
66 66
#include <net/ifq_var.h>
67 67
#include <net/if_arp.h>
68
#include <net/if_clone.h>
68 69
#include <net/route.h>
69 70

  
70 71
#include <netinet/in.h>
......
87 88
/* device */
88 89
static void		tapcreate	(cdev_t);
89 90

  
91
/* clone */
92
static int		tap_clone_create(struct if_clone *, int);
93
static void		tap_clone_destroy(struct ifnet *);
94

  
95

  
90 96
/* network interface */
91 97
static void		tapifstart	(struct ifnet *);
92 98
static int		tapifioctl	(struct ifnet *, u_long, caddr_t,
......
117 123
static int		taprefcnt = 0;		/* module ref. counter   */
118 124
static int		taplastunit = -1;	/* max. open unit number */
119 125
static int		tapdebug = 0;		/* debug flag            */
126
static int		tapuopen = 0;		/* all user open()       */
127
static int		tapuponopen = 0;	/* IFF_UP       */
120 128

  
121 129
MALLOC_DECLARE(M_TAP);
122 130
MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
131
struct if_clone tap_cloner = IF_CLONE_INITIALIZER("tap",
132
			tap_clone_create,
133
			tap_clone_destroy, 0, IF_MAXUNIT);
123 134
SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
135
SYSCTL_DECL(_net_link);
136
SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
137
    "Ethernet tunnel software network interface");
138
SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
139
	"Allow user to open /dev/tap (based on node permissions)");
140
SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
141
	"Bring interface up when /dev/tap is opened");
142
SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
143

  
124 144
DEV_MODULE(if_tap, tapmodevent, NULL);
125 145

  
126 146
/*
......
131 151
static int
132 152
tapmodevent(module_t mod, int type, void *data)
133 153
{
134
	static int		 attached = 0;
135
	struct ifnet		*ifp = NULL;
136
	int			 unit;
137

  
154
	struct tap_softc*	tp;
138 155
	switch (type) {
139 156
	case MOD_LOAD:
140
		if (attached)
157
		if (!SLIST_EMPTY(&tap_listhead))
141 158
			return (EEXIST);
142 159

  
143 160
		dev_ops_add(&tap_ops, 0, 0);
144
		attached = 1;
161
		SLIST_INIT(&tap_listhead);
162
		if_clone_attach(&tap_cloner);
163

  
145 164
		break;
146 165

  
147 166
	case MOD_UNLOAD:
148 167
		if (taprefcnt > 0)
149 168
			return (EBUSY);
150 169

  
170
		if_clone_detach(&tap_cloner);
151 171
		dev_ops_remove(&tap_ops, 0, 0);
152 172

  
153
		/* XXX: maintain tap ifs in a local list */
154
		unit = 0;
155
		while (unit <= taplastunit) {
156
			TAILQ_FOREACH(ifp, &ifnet, if_link) {
157
				if ((strcmp(ifp->if_dname, TAP) == 0) ||
158
				    (strcmp(ifp->if_dname, VMNET) == 0)) {
159
					if (ifp->if_dunit == unit)
160
						break;
161
				}
162
			}
163

  
164
			if (ifp != NULL) {
165
				struct tap_softc	*tp = ifp->if_softc;
166

  
167
				TAPDEBUG(ifp, "detached. minor = %#x, " \
168
					"taplastunit = %d\n",
169
					minor(tp->tap_dev), taplastunit);
170

  
171
				ifnet_serialize_all(ifp);
172
				tapifstop(tp, 1);
173
				ifnet_deserialize_all(ifp);
174

  
175
				ether_ifdetach(ifp);
176
				destroy_dev(tp->tap_dev);
177
				kfree(tp, M_TAP);
178
			} else {
179
				unit++;
180
			}
181
		}
182
		attached = 0;
173
		/*  maintain tap ifs in a local list */
174
		SLIST_FOREACH(tp, &tap_listhead, tap_entries)
175
			tap_clone_destroy(&tp->tap_if);
183 176
		break;
184 177

  
185 178
	default:
......
250 243
	tp->tap_flags |= TAP_INITED;
251 244
	tp->tap_devq.ifq_maxlen = ifqmaxlen;
252 245

  
246
        SLIST_INSERT_HEAD(&tap_listhead, tp, tap_entries);
247

  
253 248
	TAPDEBUG(ifp, "created. minor = %#x\n", minor(tp->tap_dev));
254 249
} /* tapcreate */
255 250

  
251
/*
252
 * tap_clone_create:
253
 *
254
 *	Create a new tap instance.
255
 */
256
static int
257
tap_clone_create(struct if_clone *ifc, int unit)
258
{
259
	struct ifnet		*ifp = NULL;
260
	struct tap_softc 	*tp = NULL;
261
	uint8_t			ether_addr[ETHER_ADDR_LEN];
262

  
263
	MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
264

  
265
	tp->tap_dev = make_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL, 
266
						0600, "%s%d", ifc->ifc_name, unit);
267
	tp->tap_dev->si_drv1 = tp;
268
	reference_dev(tp->tap_dev);	/* so we can destroy it later */
269

  
270
	/* generate fake MAC address: 00 bd xx xx xx unit_no */
271
	ether_addr[0] = 0x00;
272
	ether_addr[1] = 0xbd;
273
	bcopy(&ticks, &ether_addr[2], 3);
274
	ether_addr[5] = (u_char)unit;
275

  
276
	ifp = &tp->tap_if;
277
	ifp->if_softc = tp;
278

  
279
	if_initname(ifp, ifc->ifc_name, unit);
280
	if (unit > taplastunit)
281
		taplastunit = unit;
282

  
283
	ifp->if_init = tapifinit;
284
	ifp->if_start = tapifstart;
285
	ifp->if_ioctl = tapifioctl;
286
	ifp->if_mtu = ETHERMTU;
287
	ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
288
	ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
289
	ifq_set_ready(&ifp->if_snd);
290

  
291
	ether_ifattach(ifp, ether_addr, NULL);
292

  
293
	tp->tap_flags |= TAP_INITED;
294
	tp->tap_devq.ifq_maxlen = ifqmaxlen;
295

  
296
        SLIST_INSERT_HEAD(&tap_listhead, tp, tap_entries);
297

  
298
	TAPDEBUG(ifp, "clone created. minor = %#x tap_flags = 0x%x\n",
299
			minor(tp->tap_dev), tp->tap_flags);
300

  
301
        return (0);
302
}
303

  
256 304

  
257 305
/*
258 306
 * tapopen 
......
262 310
static int
263 311
tapopen(struct dev_open_args *ap)
264 312
{
265
	cdev_t dev = ap->a_head.a_dev;
313
	cdev_t dev = NULL;
266 314
	struct tap_softc *tp = NULL;
267 315
	struct ifnet *ifp = NULL;
268 316
	int error;
269 317

  
270
	if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0)
318
	if (tapuopen == 0 && 
319
	    (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0)
271 320
		return (error);
272 321

  
273 322
	get_mplock();
323
	dev = ap->a_head.a_dev;
274 324
	tp = dev->si_drv1;
275 325
	if (tp == NULL) {
276 326
		tapcreate(dev);
......
296 346
		fsetown(curthread->td_proc->p_pid, &tp->tap_sigtd);
297 347
	tp->tap_flags |= TAP_OPEN;
298 348
	taprefcnt ++;
349
	ifp = &tp->tap_if;
350

  
351
	if (tapuponopen)
352
		ifp->if_flags |= IFF_UP;
299 353

  
300 354
	TAPDEBUG(ifp, "opened. minor = %#x, refcnt = %d, taplastunit = %d\n",
301 355
		 minor(tp->tap_dev), taprefcnt, taplastunit);
......
366 420
	return (0);
367 421
}
368 422

  
423
/*
424
 * tap_clone_destroy:
425
 *
426
 *	Destroy a tap instance.
427
 */
428
static void
429
tap_clone_destroy(struct ifnet *ifp)
430
{
431
	struct tap_softc *tp = ifp->if_softc;
432

  
433
	TAPDEBUG(ifp, "clone destroyed. minor = %#x, refcnt = %d, taplastunit = %d\n",
434
		 minor(tp->tap_dev), taprefcnt, taplastunit);
435
	/*
436
	 * Do we really need this?
437
	 */
438
	IF_DRAIN(&ifp->if_snd);
439

  
440
	ifnet_serialize_all(ifp);
441
	tapifstop(tp, 1);
442
	ifnet_deserialize_all(ifp);
443

  
444
	ether_ifdetach(ifp);
445
	SLIST_REMOVE(&tap_listhead, tp, tap_softc, tap_entries);
446

  
447
	destroy_dev(tp->tap_dev);
448
	kfree(tp, M_TAP);
449

  
450
	taplastunit--;
451
}
369 452

  
370 453
/*
371 454
 * tapifinit
......
380 463
	struct tap_softc *tp = xtp;
381 464
	struct ifnet *ifp = &tp->tap_if;
382 465

  
383
	TAPDEBUG(ifp, "initializing, minor = %#x\n", minor(tp->tap_dev));
466
	TAPDEBUG(ifp, "initializing, minor = %#x tap_flags = 0x%x\n",
467
			minor(tp->tap_dev), tp->tap_flags);
384 468

  
385 469
	ASSERT_IFNET_SERIALIZED_ALL(ifp);
386 470

  
......
745 829
	struct mbuf		*top = NULL, **mp = NULL, *m = NULL;
746 830
	int		 	 error = 0, tlen, mlen;
747 831

  
748
	TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev));
832
//	TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev));
749 833

  
750 834
	if (uio->uio_resid == 0)
751 835
		return (0);
......
844 928
	if (ap->a_events & (POLLOUT | POLLWRNORM))
845 929
		revents |= (ap->a_events & (POLLOUT | POLLWRNORM));
846 930
	ap->a_events = revents;
847
	return(0);
931

  
932
	return revents;
848 933
}
849 934

  
850 935
/*
sys/net/tap/if_tapvar.h
61 61
	struct sigio	*tap_sigio;		/* information for async I/O */
62 62
	struct selinfo	 tap_rsel;		/* read select               */
63 63
	struct ifqueue	 tap_devq;
64

  
65
	SLIST_ENTRY(tap_softc)	tap_entries;
64 66
};
65 67

  
68
SLIST_HEAD(,tap_softc) tap_listhead;
69

  
66 70
#endif /* !_NET_IF_TAPVAR_H_ */