| 259 | } |
| 260 | |
| 261 | static int |
| 262 | in_gre_setup_socket(struct gre_softc *sc) |
| 263 | { |
| 264 | struct sockopt sopt; |
| 265 | struct sockaddr_in sin; |
| 266 | struct in_gre_socket *s; |
| 267 | struct gre_socket *gs; |
| 268 | in_addr_t addr; |
| 269 | int error, value; |
| 270 | |
| 271 | /* |
| 272 | * NOTE: we are protected with gre_ioctl_sx lock. |
| 273 | * |
| 274 | * First check that socket is already configured. |
| 275 | * If so, check that source addres was not changed. |
| 276 | * If address is different, check that there are no other tunnels |
| 277 | * and close socket. |
| 278 | */ |
| 279 | addr = sc->gre_oip.ip_src.s_addr; |
| 280 | gs = sc->gre_so; |
| 281 | if (gs != NULL) { |
| 282 | s = __containerof(gs, struct in_gre_socket, base); |
| 283 | if (s->addr != addr) { |
| 284 | if (CK_LIST_EMPTY(&gs->list)) { |
| 285 | CK_LIST_REMOVE(gs, chain); |
| 286 | soclose(gs->so); |
| 287 | NET_EPOCH_CALL(gre_sofree, &gs->epoch_ctx); |
| 288 | } |
| 289 | gs = sc->gre_so = NULL; |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | if (gs == NULL) { |
| 294 | /* |
| 295 | * Check that socket for given address is already |
| 296 | * configured. |
| 297 | */ |
| 298 | gs = in_gre_lookup_socket(addr); |
| 299 | if (gs == NULL) { |
| 300 | s = malloc(sizeof(*s), M_GRE, M_WAITOK | M_ZERO); |
| 301 | s->addr = addr; |
| 302 | gs = &s->base; |
| 303 | |
| 304 | error = socreate(sc->gre_family, &gs->so, |
| 305 | SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, |
| 306 | curthread); |
| 307 | if (error != 0) { |
| 308 | if_printf(GRE2IFP(sc), |
| 309 | "cannot create socket: %d\n", error); |
| 310 | free(s, M_GRE); |
| 311 | return (error); |
| 312 | } |
| 313 | |
| 314 | error = udp_set_kernel_tunneling(gs->so, |
| 315 | in_gre_udp_input, NULL, gs); |
| 316 | if (error != 0) { |
| 317 | if_printf(GRE2IFP(sc), |
| 318 | "cannot set UDP tunneling: %d\n", error); |
no test coverage detected