stack->port,
stack->nt ? "NT" : "TE",
stack->ptp ? "PTP" : "PMP",
- stack->l2link ? "UP " : "DOWN",
+ (stack->nt && !stack->ptp) ? "UNKN" : stack->l2link ? "UP " : "DOWN",
stack->l1link ? "UP " : "DOWN",
stack->blocked);
} else {
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
- bc->evq=EVENT_NOTHING;
-
bc->progress_coding=0;
bc->progress_location=0;
bc->progress_indicator=0;
/* Pull Up L1 */
iframe_t act;
act.prim = PH_DEACTIVATE | REQUEST;
- act.addr = stack->lower_id|FLG_MSG_DOWN;
+ act.addr = stack->upper_id | FLG_MSG_DOWN;
act.dinfo = 0;
act.len = 0;
static int misdn_lib_get_l2_down(struct misdn_stack *stack)
{
- if (stack->ptp && (stack->nt) ) {
+ if (stack->ptp && stack->nt) {
msg_t *dmsg;
/* L2 */
dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
if (stack->nst.manager_l3(&stack->nst, dmsg))
free_msg(dmsg);
pthread_mutex_unlock(&stack->nstlock);
- } else {
+ } else if (!stack->nt) {
iframe_t act;
act.prim = DL_RELEASE| REQUEST;
act.len = 0;
return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
}
+ /* cannot deestablish L2 for NT PTMP to unknown TE TEIs */
return 0;
}
/* Pull Up L1 */
iframe_t act;
act.prim = PH_ACTIVATE | REQUEST;
- act.addr = (stack->upper_id | FLG_MSG_DOWN) ;
-
+ act.addr = stack->upper_id | FLG_MSG_DOWN;
act.dinfo = 0;
act.len = 0;
+ cb_log(1, stack->port, "SENDING PH_ACTIVATE | REQ\n");
return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
-
}
int misdn_lib_get_l2_up(struct misdn_stack *stack)
{
- if (stack->ptp && (stack->nt) ) {
+ if (stack->ptp && stack->nt) {
msg_t *dmsg;
/* L2 */
dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
if (stack->nst.manager_l3(&stack->nst, dmsg))
free_msg(dmsg);
pthread_mutex_unlock(&stack->nstlock);
- } else {
+ } else if (!stack->nt) {
iframe_t act;
act.prim = DL_ESTABLISH | REQUEST;
act.len = 0;
return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
}
+ /* cannot establish L2 for NT PTMP to unknown TE TEIs */
return 0;
}
-#if 0
-static int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack)
-{
- iframe_t act;
-
- act.prim = DL_ESTABLISH | REQUEST;
- act.addr = (stack->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
-
- act.dinfo = 0;
- act.len = 0;
- return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
- return 0;
-}
-#endif
-
static int misdn_lib_get_short_status(struct misdn_stack *stack)
{
iframe_t act;
cb_log(8, port, "Init.BC %d.\n",bidx);
- bc->send_lock=malloc(sizeof(struct send_lock));
+ bc->send_lock = malloc(sizeof(struct send_lock)); /* XXX BUG! memory leak never freed */
if (!bc->send_lock) {
return -1;
}
ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff));
if (ret < 0) {
cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
+ free(stack);
return(NULL);
}
ret = mISDN_new_layer(midev, &li);
if (ret) {
cb_log(0, port, "%s: Cannot add layer %d to this port.\n", __FUNCTION__, nt?2:4);
+ free(stack);
return(NULL);
}
- stack->upper_id = li.id;
- ret = mISDN_register_layer(midev, stack->d_stid, stack->upper_id);
+ ret = mISDN_register_layer(midev, stack->d_stid, li.id);
if (ret)
{
cb_log(0,port,"Cannot register layer %d of this port.\n", nt?2:4);
+ free(stack);
return(NULL);
}
stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3);
if (stack->lower_id < 0) {
cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?1:3);
+ free(stack);
return(NULL);
}
stack->upper_id = mISDN_get_layerid(midev, stack->d_stid, nt?2:4);
if (stack->upper_id < 0) {
- cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, 2);
+ cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?2:4);
+ free(stack);
return(NULL);
}
if (stack->pri)
stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
- stack->nst.l1_id = stack->lower_id;
+ stack->nst.l1_id = stack->lower_id; /* never used */
stack->nst.l2_id = stack->upper_id;
msg_queue_init(&stack->nst.down_queue);
misdn_lib_get_short_status(stack);
misdn_lib_get_l1_up(stack);
- misdn_lib_get_l2_up(stack);
-
+ /* handle_l1 will start L2 for NT. */
+ if (!stack->nt) {
+ misdn_lib_get_l2_up(stack);
+ }
}
cb_log(8, port, "stack_init: lowerId:%x upperId:%x\n", stack->lower_id, stack->upper_id);
cleanup_Isdnl3(&stack->nst);
}
- if (stack->lower_id)
- mISDN_write_frame(stack->midev, buf, stack->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
-
if (stack->upper_id)
mISDN_write_frame(stack->midev, buf, stack->upper_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
}
-static struct misdn_bchannel *find_bc_by_channel(int port, int channel)
-{
- struct misdn_stack *stack = find_stack_by_port(port);
- int i;
-
- if (!stack) {
- return NULL;
- }
-
- for (i = 0; i <= stack->b_num; i++) {
- if (stack->bc[i].in_use && stack->bc[i].channel == channel) {
- return &stack->bc[i];
- }
- }
-
- return NULL;
-}
-
-
-
-
-
static int handle_event_te(struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
{
struct misdn_stack *stack=get_stack_by_bc(bc);
if (!stack->l1link)
misdn_lib_get_l1_up(stack);
- if (!stack->l2link)
+ /* handle_l1 will start L2 for NT. */
+ if (!stack->l2link && !stack->nt) {
misdn_lib_get_l2_up(stack);
+ }
return 0;
}
case DL_RELEASE | INDICATION:
case DL_RELEASE | CONFIRM:
+ cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
if (stack->ptp) {
- cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n");
if (stack->l2upcnt>3) {
cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attempts!!!\n");
stack->l2upcnt++;
}
}
-
- } else
- cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
+ }
stack->l2link = 0;
free_msg(msg);
{
iframe_t *frm = (iframe_t*) msg->data;
struct misdn_stack *stack = find_stack_by_addr(frm->addr);
- int i ;
if (!stack) return 0 ;
switch (frm->prim) {
case PH_ACTIVATE | CONFIRM:
+ /* we have to check for errors! */
+ if (frm->len) {
+ cb_log (3, stack->port, "L1: PH_ACTIVATE|REQUEST returned error!\n");
+ free_msg(msg);
+ return 1;
+ }
+ /* fall through */
case PH_ACTIVATE | INDICATION:
cb_log (3, stack->port, "L1: PH L1Link Up!\n");
stack->l1link=1;
} else {
free_msg(msg);
}
-
- for (i=0;i<=stack->b_num; i++) {
- if (stack->bc[i].evq != EVENT_NOTHING) {
- cb_log(4, stack->port, "Firing Queued Event %s because L1 got up\n", isdn_get_info(msgs_g, stack->bc[i].evq, 0));
- misdn_lib_send_event(&stack->bc[i],stack->bc[i].evq);
- stack->bc[i].evq=EVENT_NOTHING;
- }
-
- }
return 1;
case PH_ACTIVATE | REQUEST:
return 1;
case PH_DEACTIVATE | CONFIRM:
+ /* we have to check for errors! */
+ if (frm->len) {
+ cb_log (3, stack->port, "L1: PH_DEACTIVATE|REQUEST returned error!\n");
+ free_msg(msg);
+ return 1;
+ }
+ /* fall through */
case PH_DEACTIVATE | INDICATION:
cb_log (3, stack->port, "L1: PH L1Link Down! \n");
entity = frm->dinfo & 0xffff;
if (ret < mISDN_HEADER_LEN || !entity) {
fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n", strerror(errno));
- exit(-1);
+ mISDN_close(midev);
+ return -1;
}
return midev;
cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->upperid:%x\n",stack->nt, stack->upper_id);
if ( stack->nt && !stack->l1link) {
- /** Queue Event **/
- bc->evq=event;
- cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0));
misdn_lib_get_l1_up(stack);
- RETURN(0,OUT);
}
cb_log(1, stack->port,
{
int port=(frm->addr&MASTER_ID_MASK) >> 8;
int channel=(frm->addr&CHILD_ID_MASK) >> 16;
- struct misdn_bchannel *bc;
/*we flush the read buffer here*/
free_msg(msg);
return 1;
-
-
- bc = find_bc_by_channel(port, channel);
-
- if (!bc) {
- struct misdn_stack *stack = find_stack_by_port(port);
-
- if (!stack) {
- cb_log(0,0," --> stack not found\n");
- free_msg(msg);
- return 1;
- }
-
- cb_log(0,0," --> bc not found by channel\n");
- if (stack->l2link)
- misdn_lib_get_l2_down(stack);
-
- if (stack->l1link)
- misdn_lib_get_l1_down(stack);
-
- free_msg(msg);
- return 1;
- }
-
- cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state));
}
}
cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
}
+ /* Timer primitives must be handled first, because the frm->addr is a different
+ * "address space" than the stack/instance address of other Lx primitives.
+ */
+ if (handle_timers(msg)) {
+ return 0;
+ }
+
if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) {
static int unhandled_bmsg_count=1000;
if (handle_bchan(msg)) {
syslog(LOG_NOTICE,"mISDN recv: ADDR:%x PRIM:%x DINFO:%x\n", frm->addr, frm->prim, frm->dinfo);
#endif
- if (handle_timers(msg))
- return 0 ;
-
-
if (handle_mgmt(msg))
return 0 ;
int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data)
{
- struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib));
+ struct misdn_lib *mgr;
char *tok, *tokb;
char plist[1024];
int midev;
cb_event = iface->cb_event;
cb_jb_empty = iface->cb_jb_empty;
+ if (!portlist || (*portlist == 0)) {
+ return 1;
+ }
+
+ mgr = calloc(1, sizeof(*mgr));
+ if (!mgr) {
+ return 1;
+ }
glob_mgr = mgr;
msg_init();
misdn_lib_nt_debug_init(0,NULL);
- if (!portlist || (*portlist == 0) ) return 1;
-
init_flip_bits();
- {
- strncpy(plist,portlist, 1024);
- plist[1023] = 0;
- }
+ strncpy(plist, portlist, 1024);
+ plist[1023] = 0;
memcpy(tone_425_flip,tone_425,TONE_425_SIZE);
flip_buf_bits(tone_425_flip,TONE_425_SIZE);
flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE);
midev=te_lib_init();
+ if (midev <= 0) {
+ free(glob_mgr);
+ glob_mgr = NULL;
+ return 1;
+ }
mgr->midev=midev;
port_count=mISDN_get_stack_count(midev);
if (port > port_count) {
cb_log(0, port, "Couldn't Initialize this port since we have only %d ports\n", port_count);
- exit(1);
+ continue;
}
stack = stack_init(midev, port, ptp);
if (!stack) {
- perror("stack_init");
- exit(1);
+ cb_log(0, port, "stack_init() failed for this port\n");
+ continue;
}
/* Initialize the B channel records for real B channels. */
r = init_bc(stack, &stack->bc[i], stack->midev, port, i);
if (r < 0) {
cb_log(0, port, "Got Err @ init_bc :%d\n", r);
- exit(1);
+ break;
}
}
+ if (i <= stack->b_num) {
+ stack_destroy(stack);
+ free(stack);
+ continue;
+ }
#if defined(AST_MISDN_ENHANCEMENTS)
/* Initialize the B channel records for REGISTER signaling links. */
for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
r = init_bc(stack, &stack->bc[i], stack->midev, port, i);
if (r < 0) {
cb_log(0, port, "Got Err @ init_bc :%d\n", r);
- exit(1);
+ break;
}
stack->bc[i].is_register_pool = 1;
}
+ if (i < ARRAY_LEN(stack->bc)) {
+ stack_destroy(stack);
+ free(stack);
+ continue;
+ }
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
/* Add the new stack to the end of the list */
}
}
+ if (!mgr->stack_list) {
+ /* no stacks were successfully initialized !? */
+ te_lib_destroy(midev);
+ free(glob_mgr);
+ glob_mgr = NULL;
+ return 1;
+ }
if (sem_init(&handler_started, 1, 0)<0)
sem_init(&handler_started, 0, 0);
cb_log(1, 0, "Closing mISDN device\n");
te_lib_destroy(glob_mgr->midev);
+ while ((help = glob_mgr->stack_list)) {
+ glob_mgr->stack_list = help->next;
+ free(help);
+ }
+ free(glob_mgr);
+ glob_mgr = NULL;
}
char *manager_isdn_get_info(enum event_e event)
if (stack->pri)
stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
- stack->nst.l1_id = stack->lower_id;
+ stack->nst.l1_id = stack->lower_id; /* never used */
stack->nst.l2_id = stack->upper_id;
msg_queue_init(&stack->nst.down_queue);
if (!stack->ptp)
misdn_lib_get_l1_up(stack);
- misdn_lib_get_l2_up(stack);
}
}