| 1308 | } |
| 1309 | |
| 1310 | static int |
| 1311 | lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) |
| 1312 | { |
| 1313 | struct epoch_tracker et; |
| 1314 | struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; |
| 1315 | struct lagg_reqall *ra = (struct lagg_reqall *)data; |
| 1316 | struct lagg_reqopts *ro = (struct lagg_reqopts *)data; |
| 1317 | struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf; |
| 1318 | struct lagg_reqflags *rf = (struct lagg_reqflags *)data; |
| 1319 | struct ifreq *ifr = (struct ifreq *)data; |
| 1320 | struct lagg_port *lp; |
| 1321 | struct ifnet *tpif; |
| 1322 | struct thread *td = curthread; |
| 1323 | char *buf, *outbuf; |
| 1324 | int count, buflen, len, error = 0, oldmtu; |
| 1325 | |
| 1326 | bzero(&rpbuf, sizeof(rpbuf)); |
| 1327 | |
| 1328 | /* XXX: This can race with lagg_clone_destroy. */ |
| 1329 | |
| 1330 | switch (cmd) { |
| 1331 | case SIOCGLAGG: |
| 1332 | LAGG_XLOCK(sc); |
| 1333 | buflen = sc->sc_count * sizeof(struct lagg_reqport); |
| 1334 | outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); |
| 1335 | ra->ra_proto = sc->sc_proto; |
| 1336 | lagg_proto_request(sc, &ra->ra_psc); |
| 1337 | count = 0; |
| 1338 | buf = outbuf; |
| 1339 | len = min(ra->ra_size, buflen); |
| 1340 | CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { |
| 1341 | if (len < sizeof(rpbuf)) |
| 1342 | break; |
| 1343 | |
| 1344 | lagg_port2req(lp, &rpbuf); |
| 1345 | memcpy(buf, &rpbuf, sizeof(rpbuf)); |
| 1346 | count++; |
| 1347 | buf += sizeof(rpbuf); |
| 1348 | len -= sizeof(rpbuf); |
| 1349 | } |
| 1350 | LAGG_XUNLOCK(sc); |
| 1351 | ra->ra_ports = count; |
| 1352 | ra->ra_size = count * sizeof(rpbuf); |
| 1353 | error = copyout(outbuf, ra->ra_port, ra->ra_size); |
| 1354 | free(outbuf, M_TEMP); |
| 1355 | break; |
| 1356 | case SIOCSLAGG: |
| 1357 | error = priv_check(td, PRIV_NET_LAGG); |
| 1358 | if (error) |
| 1359 | break; |
| 1360 | if (ra->ra_proto >= LAGG_PROTO_MAX) { |
| 1361 | error = EPROTONOSUPPORT; |
| 1362 | break; |
| 1363 | } |
| 1364 | /* Infiniband only supports the failover protocol. */ |
| 1365 | if (ra->ra_proto != LAGG_PROTO_FAILOVER && |
| 1366 | ifp->if_type == IFT_INFINIBAND) { |
| 1367 | error = EPROTONOSUPPORT; |
nothing calls this directly
no test coverage detected