int sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(void *) val; syscallarg(unsigned int *) avalsize; } */ struct sockopt sopt; struct socket *so; file_t *fp; unsigned int valsize, len; int error; if (SCARG(uap, val) != NULL) { error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize)); if (error) return error; } else valsize = 0; if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) return (error); sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0); if (fp->f_flag & FNOSIGPIPE) so->so_options |= SO_NOSIGPIPE; else so->so_options &= ~SO_NOSIGPIPE; error = sogetopt(so, &sopt); if (error) goto out; if (valsize > 0) { len = min(valsize, sopt.sopt_size); error = copyout(sopt.sopt_data, SCARG(uap, val), len); if (error) goto out; error = copyout(&len, SCARG(uap, avalsize), sizeof(len)); if (error) goto out; } out: sockopt_destroy(&sopt); fd_putfile(SCARG(uap, s)); return error; }
static int bthidev_detach(device_t self, int flags) { struct bthidev_softc *sc = device_private(self); struct bthidev *hidev; mutex_enter(bt_lock); sc->sc_flags = 0; /* disable reconnecting */ /* release interrupt listen */ if (sc->sc_int_l != NULL) { l2cap_detach(&sc->sc_int_l); sc->sc_int_l = NULL; } /* release control listen */ if (sc->sc_ctl_l != NULL) { l2cap_detach(&sc->sc_ctl_l); sc->sc_ctl_l = NULL; } /* close interrupt channel */ if (sc->sc_int != NULL) { l2cap_disconnect(sc->sc_int, 0); l2cap_detach(&sc->sc_int); sc->sc_int = NULL; } /* close control channel */ if (sc->sc_ctl != NULL) { l2cap_disconnect(sc->sc_ctl, 0); l2cap_detach(&sc->sc_ctl); sc->sc_ctl = NULL; } callout_halt(&sc->sc_reconnect, bt_lock); callout_destroy(&sc->sc_reconnect); mutex_exit(bt_lock); /* detach children */ while ((hidev = LIST_FIRST(&sc->sc_list)) != NULL) { LIST_REMOVE(hidev, sc_next); config_detach(hidev->sc_dev, flags); } sockopt_destroy(&sc->sc_mode); return 0; }
int sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(const void *) val; syscallarg(unsigned int) valsize; } */ struct sockopt sopt; struct socket *so; file_t *fp; int error; unsigned int len; len = SCARG(uap, valsize); if (len > 0 && SCARG(uap, val) == NULL) return EINVAL; if (len > MCLBYTES) return EINVAL; if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) return (error); sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len); if (len > 0) { error = copyin(SCARG(uap, val), sopt.sopt_data, len); if (error) goto out; } error = sosetopt(so, &sopt); if (so->so_options & SO_NOSIGPIPE) atomic_or_uint(&fp->f_flag, FNOSIGPIPE); else atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE); out: sockopt_destroy(&sopt); fd_putfile(SCARG(uap, s)); return error; }
int ultrix_sys_setsockopt(struct lwp *l, const struct ultrix_sys_setsockopt_args *uap, register_t *retval) { struct sockopt sopt; struct socket *so; int error; struct sys_setsockopt_args ap; SCARG(&ap, s) = SCARG(uap, s); SCARG(&ap, level) = SCARG(uap, level); SCARG(&ap, name) = SCARG(uap, name); SCARG(&ap, val) = SCARG(uap, val); SCARG(&ap, valsize) = SCARG(uap, valsize); /* fd_getsock() will use the descriptor for us */ if ((error = fd_getsock(SCARG(&ap, s), &so)) != 0) return error; #define SO_DONTLINGER (~SO_LINGER) if (SCARG(&ap, name) == SO_DONTLINGER) { struct linger lg; lg.l_onoff = 0; error = so_setsockopt(l, so, SCARG(&ap, level), SO_LINGER, &lg, sizeof(lg)); goto out; } if (SCARG(&ap, level) == IPPROTO_IP) { #define EMUL_IP_MULTICAST_IF 2 #define EMUL_IP_MULTICAST_TTL 3 #define EMUL_IP_MULTICAST_LOOP 4 #define EMUL_IP_ADD_MEMBERSHIP 5 #define EMUL_IP_DROP_MEMBERSHIP 6 static const int ipoptxlat[] = { IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP }; if (SCARG(&ap, name) >= EMUL_IP_MULTICAST_IF && SCARG(&ap, name) <= EMUL_IP_DROP_MEMBERSHIP) { SCARG(&ap, name) = ipoptxlat[SCARG(&ap, name) - EMUL_IP_MULTICAST_IF]; } } if (SCARG(&ap, valsize) > MLEN) { error = EINVAL; goto out; } sockopt_init(&sopt, SCARG(&ap, level), SCARG(&ap, name), SCARG(&ap, valsize)); if (SCARG(&ap, val)) { error = copyin(SCARG(&ap, val), sopt.sopt_data, (u_int)SCARG(&ap, valsize)); } if (error == 0) error = sosetopt(so, &sopt); sockopt_destroy(&sopt); out: fd_putfile(SCARG(uap, s)); return error; }
static int btsco_open(void *hdl, int flags) { struct sockaddr_bt sa; struct btsco_softc *sc = hdl; struct sockopt sopt; int err, timo; DPRINTF("%s flags 0x%x\n", sc->sc_name, flags); /* flags FREAD & FWRITE? */ if (sc->sc_sco != NULL || sc->sc_sco_l != NULL) return EIO; KASSERT(mutex_owned(bt_lock)); memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); if (sc->sc_flags & BTSCO_LISTEN) { err = sco_attach_pcb(&sc->sc_sco_l, &btsco_sco_proto, sc); if (err) goto done; err = sco_bind_pcb(sc->sc_sco_l, &sa); if (err) { sco_detach_pcb(&sc->sc_sco_l); goto done; } err = sco_listen_pcb(sc->sc_sco_l); if (err) { sco_detach_pcb(&sc->sc_sco_l); goto done; } timo = 0; /* no timeout */ } else { err = sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc); if (err) goto done; err = sco_bind_pcb(sc->sc_sco, &sa); if (err) { sco_detach_pcb(&sc->sc_sco); goto done; } bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); err = sco_connect_pcb(sc->sc_sco, &sa); if (err) { sco_detach_pcb(&sc->sc_sco); goto done; } timo = BTSCO_TIMEOUT; } sc->sc_state = BTSCO_WAIT_CONNECT; while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT) err = cv_timedwait_sig(&sc->sc_connect, bt_lock, timo); switch (sc->sc_state) { case BTSCO_CLOSED: /* disconnected */ err = sc->sc_err; /* fall through to */ case BTSCO_WAIT_CONNECT: /* error */ if (sc->sc_sco != NULL) sco_detach_pcb(&sc->sc_sco); if (sc->sc_sco_l != NULL) sco_detach_pcb(&sc->sc_sco_l); break; case BTSCO_OPEN: /* hurrah */ sockopt_init(&sopt, BTPROTO_SCO, SO_SCO_MTU, 0); (void)sco_getopt(sc->sc_sco, &sopt); (void)sockopt_get(&sopt, &sc->sc_mtu, sizeof(sc->sc_mtu)); sockopt_destroy(&sopt); break; default: UNKNOWN(sc->sc_state); break; } done: DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n", err, sc->sc_state, sc->sc_mtu); return err; }
static int bthidev_detach(device_t self, int flags) { struct bthidev_softc *sc = device_private(self); struct bthidev *hidev; mutex_enter(bt_lock); sc->sc_flags = 0; /* disable reconnecting */ /* release interrupt listen */ if (sc->sc_int_l != NULL) { l2cap_detach_pcb(&sc->sc_int_l); sc->sc_int_l = NULL; } /* release control listen */ if (sc->sc_ctl_l != NULL) { l2cap_detach_pcb(&sc->sc_ctl_l); sc->sc_ctl_l = NULL; } /* close interrupt channel */ if (sc->sc_int != NULL) { l2cap_disconnect_pcb(sc->sc_int, 0); l2cap_detach_pcb(&sc->sc_int); sc->sc_int = NULL; } /* close control channel */ if (sc->sc_ctl != NULL) { l2cap_disconnect_pcb(sc->sc_ctl, 0); l2cap_detach_pcb(&sc->sc_ctl); sc->sc_ctl = NULL; } callout_halt(&sc->sc_reconnect, bt_lock); callout_destroy(&sc->sc_reconnect); mutex_exit(bt_lock); pmf_device_deregister(self); /* kill off the input processor */ if (sc->sc_lwp != NULL) { mutex_enter(&sc->sc_lock); sc->sc_detach = 1; cv_signal(&sc->sc_cv); mutex_exit(&sc->sc_lock); kthread_join(sc->sc_lwp); sc->sc_lwp = NULL; } /* detach children */ while ((hidev = LIST_FIRST(&sc->sc_list)) != NULL) { LIST_REMOVE(hidev, sc_next); config_detach(hidev->sc_dev, flags); } MBUFQ_DRAIN(&sc->sc_inq); cv_destroy(&sc->sc_cv); mutex_destroy(&sc->sc_lock); sockopt_destroy(&sc->sc_mode); return 0; }