static int ng_bt3c_rcvmsg(node_p node, item_p item, hook_p lasthook) { bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); struct ng_mesg *msg = NULL, *rsp = NULL; int error = 0; if (sc == NULL) { NG_FREE_ITEM(item); return (EHOSTDOWN); } NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_GENERIC_COOKIE: switch (msg->header.cmd) { case NGM_TEXT_STATUS: NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT); if (rsp == NULL) error = ENOMEM; else snprintf(rsp->data, NG_TEXTRESPONSE, "Hook: %s\n" \ "Flags: %#x\n" \ "Debug: %d\n" \ "State: %d\n" \ "IncmQ: [len:%d,max:%d]\n" \ "OutgQ: [len:%d,max:%d]\n", (sc->hook != NULL)? NG_BT3C_HOOK : "", sc->flags, sc->debug, sc->state, _IF_QLEN(&sc->inq), /* XXX */ sc->inq.ifq_maxlen, /* XXX */ _IF_QLEN(&sc->outq), /* XXX */ sc->outq.ifq_maxlen /* XXX */ ); break; default: error = EINVAL; break; } break; case NGM_BT3C_COOKIE: switch (msg->header.cmd) { case NGM_BT3C_NODE_GET_STATE: NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_state_ep), M_NOWAIT); if (rsp == NULL) error = ENOMEM; else *((ng_bt3c_node_state_ep *)(rsp->data)) = sc->state; break; case NGM_BT3C_NODE_SET_DEBUG: if (msg->header.arglen != sizeof(ng_bt3c_node_debug_ep)) error = EMSGSIZE; else sc->debug = *((ng_bt3c_node_debug_ep *)(msg->data)); break; case NGM_BT3C_NODE_GET_DEBUG: NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_debug_ep), M_NOWAIT); if (rsp == NULL) error = ENOMEM; else *((ng_bt3c_node_debug_ep *)(rsp->data)) = sc->debug; break; case NGM_BT3C_NODE_GET_QLEN: NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_qlen_ep), M_NOWAIT); if (rsp == NULL) { error = ENOMEM; break; } switch (((ng_bt3c_node_qlen_ep *)(msg->data))->queue) { case NGM_BT3C_NODE_IN_QUEUE: ((ng_bt3c_node_qlen_ep *)(rsp->data))->queue = NGM_BT3C_NODE_IN_QUEUE; ((ng_bt3c_node_qlen_ep *)(rsp->data))->qlen = sc->inq.ifq_maxlen; break; case NGM_BT3C_NODE_OUT_QUEUE: ((ng_bt3c_node_qlen_ep *)(rsp->data))->queue = NGM_BT3C_NODE_OUT_QUEUE; ((ng_bt3c_node_qlen_ep *)(rsp->data))->qlen = sc->outq.ifq_maxlen; break; default: NG_FREE_MSG(rsp); error = EINVAL; break; } break; case NGM_BT3C_NODE_SET_QLEN: if (msg->header.arglen != sizeof(ng_bt3c_node_qlen_ep)){ error = EMSGSIZE; break; } if (((ng_bt3c_node_qlen_ep *)(msg->data))->qlen <= 0) { error = EINVAL; break; } switch (((ng_bt3c_node_qlen_ep *)(msg->data))->queue) { case NGM_BT3C_NODE_IN_QUEUE: sc->inq.ifq_maxlen = ((ng_bt3c_node_qlen_ep *) (msg->data))->qlen; /* XXX */ break; case NGM_BT3C_NODE_OUT_QUEUE: sc->outq.ifq_maxlen = ((ng_bt3c_node_qlen_ep *) (msg->data))->qlen; /* XXX */ break; default: error = EINVAL; break; } break; case NGM_BT3C_NODE_GET_STAT: NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_stat_ep), M_NOWAIT); if (rsp == NULL) error = ENOMEM; else bcopy(&sc->stat, rsp->data, sizeof(ng_bt3c_node_stat_ep)); break; case NGM_BT3C_NODE_RESET_STAT: NG_BT3C_STAT_RESET(sc->stat); break; case NGM_BT3C_NODE_DOWNLOAD_FIRMWARE: if (msg->header.arglen < sizeof(ng_bt3c_firmware_block_ep)) error = EMSGSIZE; else bt3c_download_firmware(sc, msg->data, msg->header.arglen); break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } NG_RESPOND_MSG(error, node, item, rsp); NG_FREE_MSG(msg); return (error); } /* ng_bt3c_rcvmsg */
/* * Receive a control message */ static int ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook) { struct thread *td = curthread->td_proc ? curthread : &thread0; /* XXX broken */ const priv_p priv = NG_NODE_PRIVATE(node); struct socket *const so = priv->so; struct ng_mesg *resp = NULL; int error = 0; struct ng_mesg *msg; NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_KSOCKET_COOKIE: switch (msg->header.cmd) { case NGM_KSOCKET_BIND: { struct sockaddr *const sa = (struct sockaddr *)msg->data; /* Sanity check */ if (msg->header.arglen < SADATA_OFFSET || msg->header.arglen < sa->sa_len) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Bind */ error = sobind(so, sa, td); break; } case NGM_KSOCKET_LISTEN: { /* Sanity check */ if (msg->header.arglen != sizeof(int32_t)) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Listen */ error = solisten(so, *((int32_t *)msg->data), td); break; } case NGM_KSOCKET_ACCEPT: { /* Sanity check */ if (msg->header.arglen != 0) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Make sure the socket is capable of accepting */ if (!(so->so_options & SO_ACCEPTCONN)) ERROUT(EINVAL); if (priv->flags & KSF_ACCEPTING) ERROUT(EALREADY); error = ng_ksocket_check_accept(priv); if (error != 0 && error != EWOULDBLOCK) ERROUT(error); /* * If a connection is already complete, take it. * Otherwise let the upcall function deal with * the connection when it comes in. */ priv->response_token = msg->header.token; priv->response_addr = NGI_RETADDR(item); if (error == 0) { ng_ksocket_finish_accept(priv); } else priv->flags |= KSF_ACCEPTING; break; } case NGM_KSOCKET_CONNECT: { struct sockaddr *const sa = (struct sockaddr *)msg->data; /* Sanity check */ if (msg->header.arglen < SADATA_OFFSET || msg->header.arglen < sa->sa_len) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Do connect */ if ((so->so_state & SS_ISCONNECTING) != 0) ERROUT(EALREADY); if ((error = soconnect(so, sa, td, TRUE)) != 0) { soclrstate(so, SS_ISCONNECTING); ERROUT(error); } if ((so->so_state & SS_ISCONNECTING) != 0) { /* We will notify the sender when we connect */ priv->response_token = msg->header.token; priv->response_addr = NGI_RETADDR(item); priv->flags |= KSF_CONNECTING; ERROUT(EINPROGRESS); } break; } case NGM_KSOCKET_GETNAME: case NGM_KSOCKET_GETPEERNAME: { struct sockaddr *sa = NULL; int len; /* Sanity check */ if (msg->header.arglen != 0) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Get function */ if (msg->header.cmd == NGM_KSOCKET_GETPEERNAME) { if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) ERROUT(ENOTCONN); error = so_pru_peeraddr(so, &sa); } else { error = so_pru_sockaddr(so, &sa); } /* Get local or peer address */ if (error != 0) goto bail; len = (sa == NULL) ? 0 : sa->sa_len; /* Send it back in a response */ NG_MKRESPONSE(resp, msg, len, M_WAITOK | M_NULLOK); if (resp == NULL) { error = ENOMEM; goto bail; } bcopy(sa, resp->data, len); bail: /* Cleanup */ if (sa != NULL) kfree(sa, M_SONAME); break; } case NGM_KSOCKET_GETOPT: { struct ng_ksocket_sockopt *ksopt = (struct ng_ksocket_sockopt *)msg->data; struct sockopt sopt; /* Sanity check */ if (msg->header.arglen != sizeof(*ksopt)) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Get response with room for option value */ NG_MKRESPONSE(resp, msg, sizeof(*ksopt) + NG_KSOCKET_MAX_OPTLEN, M_WAITOK | M_NULLOK); if (resp == NULL) ERROUT(ENOMEM); /* Get socket option, and put value in the response */ sopt.sopt_dir = SOPT_GET; sopt.sopt_level = ksopt->level; sopt.sopt_name = ksopt->name; sopt.sopt_td = NULL; sopt.sopt_valsize = NG_KSOCKET_MAX_OPTLEN; ksopt = (struct ng_ksocket_sockopt *)resp->data; sopt.sopt_val = ksopt->value; if ((error = sogetopt(so, &sopt)) != 0) { NG_FREE_MSG(resp); break; } /* Set actual value length */ resp->header.arglen = sizeof(*ksopt) + sopt.sopt_valsize; break; } case NGM_KSOCKET_SETOPT: { struct ng_ksocket_sockopt *const ksopt = (struct ng_ksocket_sockopt *)msg->data; const int valsize = msg->header.arglen - sizeof(*ksopt); struct sockopt sopt; /* Sanity check */ if (valsize < 0) ERROUT(EINVAL); if (so == NULL) ERROUT(ENXIO); /* Set socket option */ sopt.sopt_dir = SOPT_SET; sopt.sopt_level = ksopt->level; sopt.sopt_name = ksopt->name; sopt.sopt_val = ksopt->value; sopt.sopt_valsize = valsize; sopt.sopt_td = NULL; error = sosetopt(so, &sopt); break; } default: error = EINVAL; break; } break; default: error = EINVAL; break; } done: NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); return (error); }
static int ng_sscfu_rcvmsg(node_p node, item_p item, hook_p lasthook) { struct priv *priv = NG_NODE_PRIVATE(node); struct ng_mesg *resp = NULL; struct ng_mesg *msg; int error = 0; NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_GENERIC_COOKIE: switch (msg->header.cmd) { case NGM_TEXT_STATUS: NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } resp->header.arglen = text_status(node, priv, (char *)resp->data, resp->header.arglen) + 1; break; default: error = EINVAL; break; } break; case NGM_SSCFU_COOKIE: switch (msg->header.cmd) { case NGM_SSCFU_GETDEFPARAM: { struct ng_sscfu_getdefparam *p; if (msg->header.arglen != 0) { error = EINVAL; break; } NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } p = (struct ng_sscfu_getdefparam *)resp->data; p->mask = sscfu_getdefparam(&p->param); break; } case NGM_SSCFU_ENABLE: if (msg->header.arglen != 0) { error = EINVAL; break; } if (priv->enabled) { error = EISCONN; break; } priv->enabled = 1; break; case NGM_SSCFU_DISABLE: if (msg->header.arglen != 0) { error = EINVAL; break; } if (!priv->enabled) { error = ENOTCONN; break; } priv->enabled = 0; sscfu_reset(priv->sscf); break; case NGM_SSCFU_GETSTATE: if (msg->header.arglen != 0) { error = EINVAL; break; } NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT); if(resp == NULL) { error = ENOMEM; break; } *(uint32_t *)resp->data = priv->enabled ? (sscfu_getstate(priv->sscf) + 1) : 0; break; case NGM_SSCFU_GETDEBUG: if (msg->header.arglen != 0) { error = EINVAL; break; } NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT); if(resp == NULL) { error = ENOMEM; break; } *(uint32_t *)resp->data = sscfu_getdebug(priv->sscf); break; case NGM_SSCFU_SETDEBUG: if (msg->header.arglen != sizeof(uint32_t)) { error = EINVAL; break; } sscfu_setdebug(priv->sscf, *(uint32_t *)msg->data); break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); return (error); }
static int ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook) { struct ubt_softc *sc = NG_NODE_PRIVATE(node); struct ng_mesg *msg, *rsp = NULL; struct ng_bt_mbufq *q; int error = 0, queue, qlen; NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_GENERIC_COOKIE: switch (msg->header.cmd) { case NGM_TEXT_STATUS: NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT); if (rsp == NULL) { error = ENOMEM; break; } snprintf(rsp->data, NG_TEXTRESPONSE, "Hook: %s\n" \ "Task flags: %#x\n" \ "Debug: %d\n" \ "CMD queue: [have:%d,max:%d]\n" \ "ACL queue: [have:%d,max:%d]\n" \ "SCO queue: [have:%d,max:%d]", (sc->sc_hook != NULL) ? NG_UBT_HOOK : "", sc->sc_task_flags, sc->sc_debug, sc->sc_cmdq.len, sc->sc_cmdq.maxlen, sc->sc_aclq.len, sc->sc_aclq.maxlen, sc->sc_scoq.len, sc->sc_scoq.maxlen); break; default: error = EINVAL; break; } break; case NGM_UBT_COOKIE: switch (msg->header.cmd) { case NGM_UBT_NODE_SET_DEBUG: if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep)){ error = EMSGSIZE; break; } sc->sc_debug = *((ng_ubt_node_debug_ep *) (msg->data)); break; case NGM_UBT_NODE_GET_DEBUG: NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep), M_NOWAIT); if (rsp == NULL) { error = ENOMEM; break; } *((ng_ubt_node_debug_ep *) (rsp->data)) = sc->sc_debug; break; case NGM_UBT_NODE_SET_QLEN: if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) { error = EMSGSIZE; break; } queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue; qlen = ((ng_ubt_node_qlen_ep *) (msg->data))->qlen; switch (queue) { case NGM_UBT_NODE_QUEUE_CMD: q = &sc->sc_cmdq; break; case NGM_UBT_NODE_QUEUE_ACL: q = &sc->sc_aclq; break; case NGM_UBT_NODE_QUEUE_SCO: q = &sc->sc_scoq; break; default: error = EINVAL; goto done; /* NOT REACHED */ } q->maxlen = qlen; break; case NGM_UBT_NODE_GET_QLEN: if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) { error = EMSGSIZE; break; } queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue; switch (queue) { case NGM_UBT_NODE_QUEUE_CMD: q = &sc->sc_cmdq; break; case NGM_UBT_NODE_QUEUE_ACL: q = &sc->sc_aclq; break; case NGM_UBT_NODE_QUEUE_SCO: q = &sc->sc_scoq; break; default: error = EINVAL; goto done; /* NOT REACHED */ } NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_qlen_ep), M_NOWAIT); if (rsp == NULL) { error = ENOMEM; break; } ((ng_ubt_node_qlen_ep *) (rsp->data))->queue = queue; ((ng_ubt_node_qlen_ep *) (rsp->data))->qlen = q->maxlen; break; case NGM_UBT_NODE_GET_STAT: NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep), M_NOWAIT); if (rsp == NULL) { error = ENOMEM; break; } bcopy(&sc->sc_stat, rsp->data, sizeof(ng_ubt_node_stat_ep)); break; case NGM_UBT_NODE_RESET_STAT: UBT_STAT_RESET(sc); break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } done: NG_RESPOND_MSG(error, node, item, rsp); NG_FREE_MSG(msg); return (error); } /* ng_ubt_rcvmsg */