| 247 | } |
| 248 | |
| 249 | static int |
| 250 | me_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) |
| 251 | { |
| 252 | struct ifreq *ifr = (struct ifreq *)data; |
| 253 | struct sockaddr_in *src, *dst; |
| 254 | struct me_softc *sc; |
| 255 | int error; |
| 256 | |
| 257 | switch (cmd) { |
| 258 | case SIOCSIFMTU: |
| 259 | if (ifr->ifr_mtu < 576) |
| 260 | return (EINVAL); |
| 261 | ifp->if_mtu = ifr->ifr_mtu; |
| 262 | return (0); |
| 263 | case SIOCSIFADDR: |
| 264 | ifp->if_flags |= IFF_UP; |
| 265 | case SIOCSIFFLAGS: |
| 266 | case SIOCADDMULTI: |
| 267 | case SIOCDELMULTI: |
| 268 | return (0); |
| 269 | } |
| 270 | sx_xlock(&me_ioctl_sx); |
| 271 | sc = ifp->if_softc; |
| 272 | if (sc == NULL) { |
| 273 | error = ENXIO; |
| 274 | goto end; |
| 275 | } |
| 276 | error = 0; |
| 277 | switch (cmd) { |
| 278 | case SIOCSIFPHYADDR: |
| 279 | src = &((struct in_aliasreq *)data)->ifra_addr; |
| 280 | dst = &((struct in_aliasreq *)data)->ifra_dstaddr; |
| 281 | if (src->sin_family != dst->sin_family || |
| 282 | src->sin_family != AF_INET || |
| 283 | src->sin_len != dst->sin_len || |
| 284 | src->sin_len != sizeof(struct sockaddr_in)) { |
| 285 | error = EINVAL; |
| 286 | break; |
| 287 | } |
| 288 | if (src->sin_addr.s_addr == INADDR_ANY || |
| 289 | dst->sin_addr.s_addr == INADDR_ANY) { |
| 290 | error = EADDRNOTAVAIL; |
| 291 | break; |
| 292 | } |
| 293 | error = me_set_tunnel(sc, src->sin_addr.s_addr, |
| 294 | dst->sin_addr.s_addr); |
| 295 | break; |
| 296 | case SIOCDIFPHYADDR: |
| 297 | me_delete_tunnel(sc); |
| 298 | break; |
| 299 | case SIOCGIFPSRCADDR: |
| 300 | case SIOCGIFPDSTADDR: |
| 301 | if (!ME_READY(sc)) { |
| 302 | error = EADDRNOTAVAIL; |
| 303 | break; |
| 304 | } |
| 305 | src = (struct sockaddr_in *)&ifr->ifr_addr; |
| 306 | memset(src, 0, sizeof(*src)); |
nothing calls this directly
no test coverage detected