59#include <sys/kernel.h>
60#include <sys/malloc.h>
62#include <sys/syslog.h>
70#define NAME_ANNEXA NG_LMI_HOOK_ANNEXA
71#define NAME_ANNEXD NG_LMI_HOOK_ANNEXD
72#define NAME_GROUP4 NG_LMI_HOOK_GROUPOF4
73#define NAME_NONE "None"
88#define LMI_MIN_LENGTH 8
156#define SCF_CONNECTED 0x01
158#define SCF_FIXED 0x04
160#define SCF_LMITYPE 0x18
161#define SCF_NOLMI 0x00
162#define SCF_ANNEX_A 0x08
163#define SCF_ANNEX_D 0x10
164#define SCF_GROUP4 0x18
166#define SETLMITYPE(sc, annex) \
168 (sc)->flags &= ~SCF_LMITYPE; \
169 (sc)->flags |= (annex); \
172#define NOPROTO(sc) (((sc)->flags & SCF_LMITYPE) == SCF_NOLMI)
173#define ANNEXA(sc) (((sc)->flags & SCF_LMITYPE) == SCF_ANNEX_A)
174#define ANNEXD(sc) (((sc)->flags & SCF_LMITYPE) == SCF_ANNEX_D)
175#define GROUP4(sc) (((sc)->flags & SCF_LMITYPE) == SCF_GROUP4)
178#define LMI_PATIENCE 8
188 sc = malloc(
sizeof(*sc), M_NETGRAPH, M_WAITOK | M_ZERO);
218 sc->lmi_annexA = hook;
225 sc->lmi_annexD = hook;
232 sc->lmi_group4 = hook;
240 sc->lmi_channel0 = hook;
243 if (sc->lmi_channel1023)
247 sc->lmi_channel1023 = hook;
250 if (sc->lmi_channel0)
271 if (sc->livs++ >= sc->liv_per_full) {
286 sc->lmi_channel = hook;
305 sc->livs = sc->liv_per_full - 1;
318 if (sc->lmi_channel == NULL)
320 MGETHDR(m, M_NOWAIT, MT_DATA);
322 log(LOG_ERR,
"nglmi: unable to start up LMI processing\n");
325 m->m_pkthdr.rcvif = NULL;
331 (
sizeof(
struct ng_tag_prio) -
sizeof(
struct m_tag)), M_NOWAIT);
335 m_tag_prepend(m, &ptag->
tag);
339 cptr = start = mtod(m,
char *);
369 *cptr++ = sc->local_seq;
370 *cptr++ = sc->remote_seq;
374 m->m_len = m->m_pkthdr.len = cptr - start;
395 if ((sc->poll_count <= 0) || (sc->poll_count >
LMIPOLLSIZE)) {
401 switch (sc->poll_state) {
403 log(LOG_WARNING,
"nglmi: no response from exchange\n");
407 sc->lmi_channel = sc->lmi_channel0;
411 sc->lmi_channel = sc->lmi_channel1023;
415 sc->lmi_channel = sc->lmi_channel0;
419 sc->lmi_channel = sc->lmi_channel1023;
423 sc->lmi_channel = sc->lmi_channel1023;
427 sc->lmi_channel = sc->lmi_channel0;
463 pos = sprintf(arg,
"protocol %s ", sc->protoname);
465 pos += sprintf(arg + pos,
"fixed\n");
467 pos += sprintf(arg + pos,
"auto-detecting\n");
469 pos += sprintf(arg + pos,
"auto on dlci %d\n",
470 (sc->lmi_channel == sc->lmi_channel0) ?
472 pos += sprintf(arg + pos,
473 "keepalive period: %d seconds\n", sc->liv_rate);
474 pos += sprintf(arg + pos,
475 "unacknowledged keepalives: %ld\n",
481 if (sc->dlci_state[
count]) {
482 pos += sprintf(arg + pos,
483 "dlci %d %s\n",
count,
484 (sc->dlci_state[
count]
510 sc->protoname,
sizeof(stat->
proto) - 1);
512 sc->protoname,
sizeof(stat->
hook) - 1);
515 for (k = 0; k <=
MAXDLCI; k++) {
516 switch (sc->dlci_state[k]) {
518 stat->
up[k / 8] |= (1 << (k % 8));
521 stat->
seen[k / 8] |= (1 << (k % 8));
542#define STEPBY(stepsize) \
544 packetlen -= (stepsize); \
545 data += (stepsize); \
559 int resptype_seen = 0;
567 packetlen = m->m_len;
570 if ((packetlen > MHLEN) && !(m->m_flags & M_EXT)) {
571 log(LOG_WARNING,
"nglmi: packetlen (%d) too big\n", packetlen);
574 if (m->m_len < packetlen && (m = m_pullup(m, packetlen)) == NULL) {
576 "nglmi: m_pullup failed for %d bytes\n", packetlen);
583 data = mtod(m,
const u_char *);
604 log(LOG_ERR,
"nglmi: No known type\n");
607 sc->lmi_channel = hook;
608 sc->flags &= ~SCF_AUTO;
609 log(LOG_INFO,
"nglmi: auto-detected %s LMI on DLCI %d\n",
610 sc->protoname, hook == sc->lmi_channel0 ? 0 : 1023);
616 while (packetlen >= 2) {
617 u_int segtype =
data[0];
618 u_int segsize =
data[1];
622 if (packetlen < segsize + 2)
628 log(LOG_WARNING,
"nglmi: dup MSGTYPE\n");
645 int idx = sc->invalidx;
650 if (sc->dlci_state[idx] ==
DLCI_UP)
658 if (sc->livs > sc->liv_per_full)
671 sc->remote_seq =
data[2];
672 if (sc->local_seq ==
data[3]) {
677 if (sc->local_seq == 0)
688 dlci = ((u_short)
data[2] & 0xff) << 8;
695 dlci = ((u_short)
data[2] & 0x3f) << 4;
712 "nglmi: DLCI %d became active\n",
744 int resptype_seen = 0;
745 int highest_dlci = 0;
747 packetlen = m->m_len;
748 data = mtod(m,
const u_char *);
750 log(LOG_WARNING,
"nglmi: unexpected value in LMI(%d)\n", 1);
768 log(LOG_WARNING,
"nglmi: bad Protocol ID(%d)\n",
773 if (nextbyte != sc->protoID) {
774 log(LOG_WARNING,
"nglmi: unexpected Protocol ID(%d)\n",
783 log(LOG_WARNING,
"nglmi: unexpected Call Reference (0x%x)\n",
792 log(LOG_WARNING,
"nglmi: unexpected message type(0x%x)\n",
799 "nglmi: unexpected msg type(0x%x) \n", (
int)
type);
810 if (nextbyte == 0x95) {
815 }
else if (nextbyte == 0x95) {
816 log(LOG_WARNING,
"nglmi: locking shift seen in G4\n");
825 "nglmi: locking shift missing\n");
828 }
else if (*
data == 0x95) {
829 log(LOG_WARNING,
"nglmi: locking shift seen\n");
837 while (packetlen >= 2) {
838 u_int segtype =
data[0];
839 u_int segsize =
data[1];
843 if (packetlen < (segsize + 2)) {
844 log(LOG_WARNING,
"nglmi: IE longer than packet\n");
853 log(LOG_WARNING,
"nglmi: dup MSGTYPE\n");
857 log(LOG_WARNING,
"nglmi: MSGTYPE wrong size\n");
866 if (sc->livs > sc->liv_per_full) {
868 "nglmi: LIV when FULL expected\n");
879 "nglmi: Unknown report type %d\n",
data[2]);
889 if (resptype_seen == 0) {
890 log(LOG_WARNING,
"nglmi: no TYPE before SEQ\n");
896 log(LOG_WARNING,
"nglmi: bad SEQ sts size\n");
899 if (sc->local_seq !=
data[3]) {
900 log(LOG_WARNING,
"nglmi: unexpected SEQ\n");
912 "nglmi: No sequence before DLCI\n");
915 if (resptype_seen != 2) {
917 "nglmi: No resp type before DLCI\n");
923 "nglmi: wrong IE segsize\n");
926 dlci = ((u_short)
data[2] & 0xff) << 8;
931 "nglmi: DLCI headersize of %d"
932 " not supported\n", segsize - 1);
935 dlci = ((u_short)
data[2] & 0x3f) << 4;
940 if (async && highest_dlci) {
942 "nglmi: Async with > 1 DLCI\n");
954 log(LOG_WARNING,
"nglmi: DLCI out of order\n");
959 log(LOG_WARNING,
"nglmi: DLCI out of range\n");
966 "nglmi: unknown LMI segment type %d\n", segtype);
971 if (packetlen != 0) {
973 "nglmi: %d bytes extra at end of packet\n", packetlen);
976 if (resptype_seen == 0) {
977 log(LOG_WARNING,
"nglmi: No response type seen\n");
981 log(LOG_WARNING,
"nglmi: No sequence numbers seen\n");
991 const u_char *bp = mtod(m,
const u_char *);
994 loc = (m->m_len - packetlen);
995 log(LOG_WARNING,
"nglmi: error at location %d\n", loc);
996 while (k < m->m_len) {
999 while ((j++ < 16) && k < m->m_len) {
1000 pos += sprintf(buf + pos,
"%c%02x",
1001 ((loc == k) ?
'>' :
' '),
1006 log(LOG_WARNING,
"nglmi: packet data:%s\n", buf);
1008 log(LOG_WARNING,
"%04d :%s\n", k, buf);
1018 const u_char *bp = mtod(m,
const u_char *);
1021 loc = (m->m_len - packetlen);
1022 log(LOG_WARNING,
"nglmi: error at location %d\n", loc);
1023 while (k < m->m_len) {
1026 while ((j++ < 16) && k < m->m_len) {
1027 pos += sprintf(buf + pos,
"%c%02x",
1028 ((loc == k) ?
'>' :
' '),
1033 log(LOG_WARNING,
"nglmi: packet data:%s\n", buf);
1035 log(LOG_WARNING,
"%04d :%s\n", k, buf);
1054 free(sc, M_NETGRAPH);
#define NG_HOOK_NODE(hook)
#define NG_PRIO_LINKSTATE
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
int ng_disconnect_t(hook_p hook)
#define NG_NODE_SET_PRIVATE(node, val)
#define NG_RESPOND_MSG(error, here, item, resp)
#define NG_NODE_IS_VALID(node)
#define NG_NODE_UNREF(node)
#define NG_HOOK_SET_PRIVATE(hook, val)
int ng_rmnode_self(node_p here)
#define ng_callout_init(c)
#define NG_SEND_DATA_ONLY(error, hook, m)
int ng_rcvdata_t(hook_p hook, item_p item)
int ng_shutdown_t(node_p node)
int ng_uncallout(struct callout *c, node_p node)
#define NG_FREE_ITEM(item)
int ng_constructor_t(node_p node)
#define NGI_GET_MSG(i, m)
#define NG_NODE_PRIVATE(node)
int ng_callout(struct callout *c, node_p node, hook_p hook, int ticks, ng_item_fn *fn, void *arg1, int arg2)
int ng_newhook_t(node_p node, hook_p hook, const char *name)
#define NG_HOOK_PRIVATE(hook)
static ng_disconnect_t nglmi_disconnect
static void nglmi_inquire(sc_p sc, int full)
static ng_shutdown_t nglmi_shutdown
static ng_newhook_t nglmi_newhook
static ng_rcvmsg_t nglmi_rcvmsg
static void LMI_ticker(node_p node, hook_p hook, void *arg1, int arg2)
static ng_constructor_t nglmi_constructor
static ng_rcvdata_t nglmi_rcvdata
static int nglmi_checkdata(hook_p hook, struct mbuf *m)
struct nglmi_softc * sc_p
static struct ng_type typestruct
static void nglmi_startup(sc_p sc)
static void ngauto_state_machine(sc_p sc)
static void nglmi_startup_fixed(sc_p sc, hook_p hook)
static void nglmi_startup_auto(sc_p sc)
NETGRAPH_INIT(lmi, &typestruct)
#define SETLMITYPE(sc, annex)
#define NG_LMI_HOOK_AUTO1023
#define NG_LMI_HOOK_ANNEXD
#define NG_LMI_KEEPALIVE_RATE
#define NG_LMI_HOOK_GROUPOF4
#define NG_LMI_HOOK_ANNEXA
#define NG_LMI_SEQ_PER_FULL
#define NG_LMI_HOOK_DEBUG
#define NG_LMI_HOOK_AUTO0
#define NG_MKRESPONSE(rsp, msg, len, how)
#define NGM_GENERIC_COOKIE
struct ng_mesg::ng_msghdr header
u_char dlci_state[MAXDLCI+1]
u_char up[NGM_LMI_STAT_ARYSIZE]
u_char seen[NGM_LMI_STAT_ARYSIZE]