/* * CONTROL MESSAGES */ static int text_status(node_p node, struct priv *priv, char *arg, u_int len) { struct sbuf sbuf; sbuf_new(&sbuf, arg, len, 0); if (priv->upper) sbuf_printf(&sbuf, "upper hook: %s connected to %s:%s\n", NG_HOOK_NAME(priv->upper), NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))), NG_HOOK_NAME(NG_HOOK_PEER(priv->upper))); else sbuf_printf(&sbuf, "upper hook: <not connected>\n"); if (priv->lower) sbuf_printf(&sbuf, "lower hook: %s connected to %s:%s\n", NG_HOOK_NAME(priv->lower), NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))), NG_HOOK_NAME(NG_HOOK_PEER(priv->lower))); else sbuf_printf(&sbuf, "lower hook: <not connected>\n"); sbuf_printf(&sbuf, "sscf state: %s\n", priv->enabled == NULL ? "<disabled>" : sscfu_statename(sscfu_getstate(priv->sscf))); sbuf_finish(&sbuf); return (sbuf_len(&sbuf)); }
/* * Receive data on a hook */ static int ngs_rcvdata(hook_p hook, item_p item) { struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct ngpcb *const pcbp = priv->datasock; struct socket *so; struct sockaddr_ng *addr; char *addrbuf[NG_HOOKSIZ + 4]; int addrlen; struct mbuf *m; NGI_GET_M(item, m); NG_FREE_ITEM(item); /* If there is no data socket, black-hole it. */ if (pcbp == NULL) { NG_FREE_M(m); return (0); } so = pcbp->ng_socket; /* Get the return address into a sockaddr. */ addrlen = strlen(NG_HOOK_NAME(hook)); /* <= NG_HOOKSIZ - 1 */ addr = (struct sockaddr_ng *) addrbuf; addr->sg_len = addrlen + 3; addr->sg_family = AF_NETGRAPH; bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen); addr->sg_data[addrlen] = '\0'; /* Try to tell the socket which hook it came in on. */ if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)addr, m, NULL) == 0) { m_freem(m); TRAP_ERROR; return (ENOBUFS); } sorwakeup(so); return (0); }
void ng_hci_node_is_up(node_p node, hook_p hook, void *arg1, int arg2) { ng_hci_unit_p unit = NULL; struct ng_mesg *msg = NULL; ng_hci_node_up_ep *ep = NULL; int error; if (node == NULL || NG_NODE_NOT_VALID(node) || hook == NULL || NG_HOOK_NOT_VALID(hook)) return; unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node); if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) return; if (hook != unit->acl && hook != unit->sco) return; NG_MKMESSAGE(msg,NGM_HCI_COOKIE,NGM_HCI_NODE_UP,sizeof(*ep),M_NOWAIT); if (msg != NULL) { ep = (ng_hci_node_up_ep *)(msg->data); if (hook == unit->acl) { NG_HCI_BUFF_ACL_SIZE(unit->buffer, ep->pkt_size); NG_HCI_BUFF_ACL_TOTAL(unit->buffer, ep->num_pkts); } else { NG_HCI_BUFF_SCO_SIZE(unit->buffer, ep->pkt_size); NG_HCI_BUFF_SCO_TOTAL(unit->buffer, ep->num_pkts); } bcopy(&unit->bdaddr, &ep->bdaddr, sizeof(ep->bdaddr)); NG_SEND_MSG_HOOK(error, node, msg, hook, 0); } else error = ENOMEM; if (error != 0) NG_HCI_INFO( "%s: %s - failed to send NODE_UP message to hook \"%s\", error=%d\n", __func__, NG_NODE_NAME(unit->node), NG_HOOK_NAME(hook), error); } /* ng_hci_node_is_up */
static int ng_vlan_rcvmsg(node_p node, item_p item, hook_p lasthook) { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *msg, *resp = NULL; struct ng_vlan_filter *vf; hook_p hook; struct ng_vlan_table *t; uintptr_t hook_data; int i, vlan_count; uint16_t vid; int error = 0; NGI_GET_MSG(item, msg); /* Deal with message according to cookie and command. */ switch (msg->header.typecookie) { case NGM_VLAN_COOKIE: switch (msg->header.cmd) { case NGM_VLAN_ADD_FILTER: /* Check that message is long enough. */ if (msg->header.arglen != sizeof(*vf)) { error = EINVAL; break; } vf = (struct ng_vlan_filter *)msg->data; /* Sanity check the VLAN ID value. */ #ifdef NG_VLAN_USE_OLD_VLAN_NAME if (vf->vid == 0 && vf->vid != vf->vlan) { vf->vid = vf->vlan; } else if (vf->vid != 0 && vf->vlan != 0 && vf->vid != vf->vlan) { error = EINVAL; break; } #endif if (vf->vid & ~EVL_VLID_MASK || vf->pcp & ~7 || vf->cfi & ~1) { error = EINVAL; break; } /* Check that a referenced hook exists. */ hook = ng_findhook(node, vf->hook_name); if (hook == NULL) { error = ENOENT; break; } /* And is not one of the special hooks. */ if (hook == priv->downstream_hook || hook == priv->nomatch_hook) { error = EINVAL; break; } /* And is not already in service. */ if (IS_HOOK_VLAN_SET(NG_HOOK_PRIVATE(hook))) { error = EEXIST; break; } /* Check we don't already trap this VLAN. */ if (priv->vlan_hook[vf->vid] != NULL) { error = EEXIST; break; } /* Link vlan and hook together. */ NG_HOOK_SET_PRIVATE(hook, (void *)(HOOK_VLAN_TAG_SET_MASK | EVL_MAKETAG(vf->vid, vf->pcp, vf->cfi))); priv->vlan_hook[vf->vid] = hook; break; case NGM_VLAN_DEL_FILTER: /* Check that message is long enough. */ if (msg->header.arglen != NG_HOOKSIZ) { error = EINVAL; break; } /* Check that hook exists and is active. */ hook = ng_findhook(node, (char *)msg->data); if (hook == NULL) { error = ENOENT; break; } hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook); if (IS_HOOK_VLAN_SET(hook_data) == 0) { error = ENOENT; break; } KASSERT(priv->vlan_hook[EVL_VLANOFTAG(hook_data)] == hook, ("%s: NGM_VLAN_DEL_FILTER: Invalid VID for Hook = %s\n", __func__, (char *)msg->data)); /* Purge a rule that refers to this hook. */ priv->vlan_hook[EVL_VLANOFTAG(hook_data)] = NULL; NG_HOOK_SET_PRIVATE(hook, NULL); break; case NGM_VLAN_DEL_VID_FLT: /* Check that message is long enough. */ if (msg->header.arglen != sizeof(uint16_t)) { error = EINVAL; break; } vid = (*((uint16_t *)msg->data)); /* Sanity check the VLAN ID value. */ if (vid & ~EVL_VLID_MASK) { error = EINVAL; break; } /* Check that hook exists and is active. */ hook = priv->vlan_hook[vid]; if (hook == NULL) { error = ENOENT; break; } hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook); if (IS_HOOK_VLAN_SET(hook_data) == 0) { error = ENOENT; break; } KASSERT(EVL_VLANOFTAG(hook_data) == vid, ("%s: NGM_VLAN_DEL_VID_FLT:" " Invalid VID Hook = %us, must be: %us\n", __func__, (uint16_t )EVL_VLANOFTAG(hook_data), vid)); /* Purge a rule that refers to this hook. */ priv->vlan_hook[vid] = NULL; NG_HOOK_SET_PRIVATE(hook, NULL); break; case NGM_VLAN_GET_TABLE: /* Calculate vlans. */ vlan_count = 0; for (i = 0; i < (EVL_VLID_MASK + 1); i ++) { if (priv->vlan_hook[i] != NULL && NG_HOOK_IS_VALID(priv->vlan_hook[i])) vlan_count ++; } /* Allocate memory for responce. */ NG_MKRESPONSE(resp, msg, sizeof(*t) + vlan_count * sizeof(*t->filter), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } /* Pack data to responce. */ t = (struct ng_vlan_table *)resp->data; t->n = 0; vf = &t->filter[0]; for (i = 0; i < (EVL_VLID_MASK + 1); i ++) { hook = priv->vlan_hook[i]; if (hook == NULL || NG_HOOK_NOT_VALID(hook)) continue; hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook); if (IS_HOOK_VLAN_SET(hook_data) == 0) continue; KASSERT(EVL_VLANOFTAG(hook_data) == i, ("%s: NGM_VLAN_GET_TABLE:" " hook %s VID = %us, must be: %i\n", __func__, NG_HOOK_NAME(hook), (uint16_t)EVL_VLANOFTAG(hook_data), i)); #ifdef NG_VLAN_USE_OLD_VLAN_NAME vf->vlan = i; #endif vf->vid = i; vf->pcp = EVL_PRIOFTAG(hook_data); vf->cfi = EVL_CFIOFTAG(hook_data); strncpy(vf->hook_name, NG_HOOK_NAME(hook), NG_HOOKSIZ); vf ++; t->n ++; } break; case NGM_VLAN_GET_DECAP: NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } (*((uint32_t *)resp->data)) = priv->decap_enable; break; case NGM_VLAN_SET_DECAP: if (msg->header.arglen != sizeof(uint32_t)) { error = EINVAL; break; } priv->decap_enable = (*((uint32_t *)msg->data)); break; case NGM_VLAN_GET_ENCAP: NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } (*((uint32_t *)resp->data)) = priv->encap_enable; break; case NGM_VLAN_SET_ENCAP: if (msg->header.arglen != sizeof(uint32_t)) { error = EINVAL; break; } priv->encap_enable = (*((uint32_t *)msg->data)); break; case NGM_VLAN_GET_ENCAP_PROTO: NG_MKRESPONSE(resp, msg, sizeof(uint16_t), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } (*((uint16_t *)resp->data)) = ntohs(priv->encap_proto); break; case NGM_VLAN_SET_ENCAP_PROTO: if (msg->header.arglen != sizeof(uint16_t)) { error = EINVAL; break; } priv->encap_proto = htons((*((uint16_t *)msg->data))); break; default: /* Unknown command. */ error = EINVAL; break; } break; case NGM_FLOW_COOKIE: { struct ng_mesg *copy; /* * Flow control messages should come only * from downstream. */ if (lasthook == NULL) break; if (lasthook != priv->downstream_hook) break; /* Broadcast the event to all uplinks. */ for (i = 0; i < (EVL_VLID_MASK + 1); i ++) { if (priv->vlan_hook[i] == NULL) continue; NG_COPYMESSAGE(copy, msg, M_NOWAIT); if (copy == NULL) continue; NG_SEND_MSG_HOOK(error, node, copy, priv->vlan_hook[i], 0); } break; } default: /* Unknown type cookie. */ error = EINVAL; break; } NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); return (error); }
/* * Produce a readable status description */ static int text_status(node_p node, struct priv *priv, char *arg, u_int len) { struct sbuf sbuf; sbuf_new(&sbuf, arg, len, 0); if (priv->upper) sbuf_printf(&sbuf, "upper hook: %s connected to %s:%s\n", NG_HOOK_NAME(priv->upper), NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))), NG_HOOK_NAME(NG_HOOK_PEER(priv->upper))); else sbuf_printf(&sbuf, "upper hook: <not connected>\n"); if (priv->lower) sbuf_printf(&sbuf, "lower hook: %s connected to %s:%s\n", NG_HOOK_NAME(priv->lower), NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))), NG_HOOK_NAME(NG_HOOK_PEER(priv->lower))); else sbuf_printf(&sbuf, "lower hook: <not connected>\n"); if (priv->manage) sbuf_printf(&sbuf, "manage hook: %s connected to %s:%s\n", NG_HOOK_NAME(priv->manage), NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->manage))), NG_HOOK_NAME(NG_HOOK_PEER(priv->manage))); else sbuf_printf(&sbuf, "manage hook: <not connected>\n"); sbuf_printf(&sbuf, "sscop state: %s\n", !priv->enabled ? "<disabled>" : sscop_statename(sscop_getstate(priv->sscop))); sbuf_printf(&sbuf, "input packets: %ju\n", (uintmax_t)priv->stats.in_packets); sbuf_printf(&sbuf, "input dropped: %ju\n", (uintmax_t)priv->stats.in_dropped); sbuf_printf(&sbuf, "output packets: %ju\n", (uintmax_t)priv->stats.out_packets); sbuf_printf(&sbuf, "output dropped: %ju\n", (uintmax_t)priv->stats.out_dropped); sbuf_printf(&sbuf, "aa signals: %ju\n", (uintmax_t)priv->stats.aa_signals); sbuf_printf(&sbuf, "aa dropped: %ju\n", (uintmax_t)priv->stats.aa_dropped); sbuf_printf(&sbuf, "maa signals: %ju\n", (uintmax_t)priv->stats.maa_signals); sbuf_printf(&sbuf, "maa dropped: %ju\n", (uintmax_t)priv->stats.maa_dropped); sbuf_printf(&sbuf, "errors: %ju\n", (uintmax_t)priv->stats.errors); sbuf_printf(&sbuf, "data delivered: %ju\n", (uintmax_t)priv->stats.data_delivered); sbuf_printf(&sbuf, "window: %u\n", sscop_window(priv->sscop, 0)); sbuf_finish(&sbuf); return (sbuf_len(&sbuf)); }