RLT Feature using asterisk & libss7

Can anyone suggest a way forward to implement RLT feature with asterisk and libss7?

to accomplish this feature, we need to do the following:

1.Release the call with cause code(23).
2.Send the redirection number in the REL Message part on ISUP.

I am able to release the call with cause code(23).

But unable to send redirection number in REL Message part on ISUP.

Currently i am using Atilla’s patch version of libss7.

We have Implemented RLT features by adding the below patches.

Asterisk Patches :-
chan_dahdi.c :

a703 1
char redirect_value[50];
a3257 1
ast_log(LOG_WARNING, “Orig Called Num 1 : %s\n”, p->origcid_num);
d3408 1
a3408 2
const char *cause = NULL;
cause = pbx_builtin_getvar_helper(ast,“SS7_CAUSE”);
d3410 1
d3415 1
a3415 29
if(icause == 23)
{
const char *redirection_number = NULL;
const char *redirection_counter;
const char *redirect_info_ind;
const char *redirect_info_orig_areas;
const char *redirect_info_counter;
const char *redirect_info_reas;

                                                    redirect_info_ind = pbx_builtin_getvar_helper(ast, "SS7_REL_REDIRECT_INFO_IND");
                                                    redirect_info_orig_areas = pbx_builtin_getvar_helper(ast, "SS7_REL_REDIRECT_INFO_ORIG_REAS");
                                                    redirect_info_counter = pbx_builtin_getvar_helper(ast, "SS7_REL_REDIRECT_INFO_COUNTER");
                                                    redirect_info_reas = pbx_builtin_getvar_helper(ast, "SS7_REL_REDIRECT_INFO_REAS");
						
						ast_log(LOG_WARNING, "Redirect Info Value : %s\n", redirect_info_ind);
						ast_log(LOG_WARNING, "Redirect Info Orginal  Value : %s\n", redirect_info_orig_areas);
						ast_log(LOG_WARNING, "Redirect Info Counter Value : %s\n", redirect_info_counter);
						ast_log(LOG_WARNING, "Redirect Info Reason Value : %s\n", redirect_info_reas);
						
						isup_set_redirectiong_info_reason(p->ss7->ss7, p->ss7call, atoi(redirect_info_ind), atoi(redirect_info_orig_areas), atoi(redirect_info_counter), atoi(redirect_info_reas));	
						redirection_counter = pbx_builtin_getvar_helper(ast, "SS7_REL_REDIRECTION_COUNTER");
						isup_set_redirection_counter(p->ss7->ss7, p->ss7call, atoi(redirection_counter));	
							
    	                                        redirection_number = pbx_builtin_getvar_helper(ast, "SS7_REL_REDIRECTION_NUMBER");
						isup_set_redirection_number(p->ss7->ss7, p->ss7call, redirection_number);

					}
					else if(icause > 255)
					{

a3416 2
}

LibSS7 Patches:-
isup.c :

d88 1
a88 1
static int rel_params[] = { ISUP_PARM_CAUSE, ISUP_PARM_REDIRECTION_INFO, ISUP_PARM_REDIRECTION_NUMBER, ISUP_PARM_REDIRECT_COUNTER, -1};
a800 2
//int oddeven = (parm[0] >> 7) & 0x1;
//int redirnum;
d804 1
a804 1
//redirnum = ((parm[2] & 0x60) >> 5);
a809 2
//int oddeven, datalen;
//int redirnum;
a811 1
//parm[2] = 0x80 | redirnum;
a817 1
//int redirnum;
d918 1
a1613 113

static FUNC_DUMP(redirection_reas_info_dump)
{
char *redirect_ind, *orig_redir_reas, *redir_reas;

    switch (parm[0] & 0x7) {
            case 0:
                    redirect_ind = "No Redirection (national use)";
                    break;
            case 1:
                    redirect_ind = "Call rerouted (national use)";
                    break;
            case 2:
                    redirect_ind = "Call rerouted, all rediection information presentation restricted (national use)";
                    break;
            case 3:
                    redirect_ind = "Call diverted";
                    break;
            case 4:
                    redirect_ind = "Call diverted, all redirection information presentation restricted";
                    break;
            case 5:
                    redirect_ind = "Call rerouted, redirection number presentation restricted (national use)";
                    break;
            case 6:
                    redirect_ind = "Call diversion, redirection number presentation restricted (national use)";
                    break;
            case 7:
                    redirect_ind = "spare";
                    break;
            default:
                    redirect_ind = "Unknown";
                    break;
    }
    
    
    ss7_message(ss7, "\t\t\tRedirecting indicator: %s (%d)\n", redirect_ind, parm[0] & 0x7);

        switch ((parm[0] >> 4) & 0xf) {
                case 0:
                        orig_redir_reas = "Unknown/not available";
                        break;
                case 1:
                        orig_redir_reas = "User busy (national use)";
                        break;
                case 2:
                        orig_redir_reas = "No reply (national use)";
                        break;
                case 3:
                        orig_redir_reas = "Unconditional (national use)";
                        break;
                default:
                        orig_redir_reas = "spare";
                        break;
    }
    
    ss7_message(ss7, "\t\t\tOriginal redirection reason: %s (%d)\n", orig_redir_reas, (parm[0] >> 4) & 0xf);
        ss7_message(ss7, "\t\t\tRedirection counter: %d\n", parm[1] & 0x7);

        switch ((parm[1] >> 4) & 0xf) {
                case 0:
                        redir_reas = "Unknown/not available";
                        break;
                case 1:
                        redir_reas = "User busy";
                        break;
                case 2:
                        redir_reas = "No reply";
                        break;
                case 3:
                        redir_reas = "Unconditional";
                        break;
                case 4:
                        redir_reas = "Deflection during alerting";
                        break;
                case 5:
                        redir_reas = "Deflection immediate response";
                        break;
                case 6:
                        redir_reas = "Mobile subscriber not reachable";
                        break;
                default:
                        redir_reas = "spare";
                        break;
    }
    
    ss7_message(ss7, "\t\t\tRedirecting reason: %s (%d)\n", redir_reas, (parm[1] >> 4) & 0xf);

        return 2;
}

static FUNC_RECV(redirection_reas_info_receive)
{
        c->redirect_info = 1;
        c->redirect_info_ind = parm[0] & 0x7;
        c->redirect_info_orig_reas = (parm[0] >> 4) & 0xf;
        c->redirect_info_counter = parm[1] & 0x7;
        c->redirect_info_reas = (parm[1] >> 4) & 0xf;
        return 2;
}

static FUNC_SEND(redirection_reas_info_transmit)
{
        if (!c->redirect_info)
                return 0;

        parm[0] = (c->redirect_info_ind & 0x7) | ((c->redirect_info_orig_reas << 4) & 0xf0);
        parm[1] = (c->redirect_info_counter & 0x7) | ((c->redirect_info_reas << 4) & 0xf0);
        return 2;

}

a2205 48

static FUNC_DUMP(redirection_number_dump)
{
int oddeven = (parm[0] >> 7) & 0x1;
char numbuf[64] = “”;
isup_get_number(numbuf, &parm[2], len - 2, oddeven);

ss7_message(ss7, "\t\t\tNature of address: %x\n", parm[0] & 0x7f);
    ss7_message(ss7, "\t\t\tNI: %x\n", (parm[1] >> 7) & 0x1);
    ss7_message(ss7, "\t\t\tNumbering plan: %x\n", (parm[1] >> 4) & 0x7);
    ss7_message(ss7, "\t\t\tPresentation: %x\n", (parm[1] >> 2) & 0x3);
    ss7_message(ss7, "\t\t\tScreening: %x\n", parm[1] & 0x3);
    ss7_message(ss7, "\t\t\tRedirection Number : %s\n", numbuf);

    return len;

}

static FUNC_RECV(redirection_number_receive)
{
int oddeven = (parm[0] >> 7) & 0x1;

    isup_get_number(c->redirecting_num, &parm[2], len - 2, oddeven);
    
c->redirecting_num_nai = parm[0] & 0x7f;                /* Nature of Address Indicator */
    c->redirecting_num_presentation_ind = (parm[1] >> 2) & 0x3;
    c->redirecting_num_screening_ind = parm[1] & 0x3;

return len;

}

static FUNC_SEND(redirection_number_transmit)
{
int oddeven, datalen;

    if (!c->redirecting_num[0])
            return 0;
    isup_put_number(&parm[2], c->redirecting_num, &datalen, &oddeven);
    parm[0] = (oddeven << 7) | c->redirecting_num_nai;      /* Nature of Address Indicator */
    parm[1] = (1 << 4) |                            /* Assume E.164 ISDN numbering plan, calling number complete */
            ((c->redirecting_num_presentation_ind & 0x3) << 2) |
            (c->redirecting_num_screening_ind & 0x3);

return datalen + 2;

}

a2223 2

a2274 21
static FUNC_DUMP(redirection_counter_dump)
{
ss7_message(ss7, “\t\t\tRedirection count : %i\n”, parm[0] & 0x1f);
return 1;
}

static FUNC_RECV(redirection_counter_receive)
{
c->redirect_counter = parm[0] & 0x1f;
return 1;
}

static FUNC_SEND(redirection_counter_transmit)
{
if (!c->redirect_counter)
return 0;

    parm[0] = c->redirect_counter & 0x1f;
    return 1;

}

a2468 1
{ISUP_PARM_REDIRECTION_INFO_REASON, “Redirection Information Reason”, redirection_reas_info_dump, redirection_reas_info_receive, redirection_reas_info_transmit},
a2476 1
{ISUP_PARM_REDIRECTION_NUMBER, “Redirection Number”, redirection_number_dump, redirection_number_receive, redirection_number_transmit},
a2478 1
{ISUP_PARM_REDIRECTION_COUNTER, “Redirection Counter”, redirection_counter_dump, redirection_counter_receive, redirection_counter_transmit},
a2588 16
void isup_set_redirection_number(struct ss7 *ss7, struct isup_call *c, const char *redirecting_number)
{
if (redirecting_number && redirecting_number[0]) {
strncpy(c->redirecting_num, redirecting_number, sizeof(c->redirecting_num));
ss7_message(ss7, “\t\tRedirecting NUmber Value (%s):\n”, c->redirecting_num);
c->redirecting_num_nai = 3;
c->redirecting_num_presentation_ind = 1;
c->redirecting_num_screening_ind = 3;
ss7_message(ss7, “\t\tRedirecting Nature of Address (%d):\n”, c->redirecting_num_nai);
ss7_message(ss7, “\t\tRedirecting Presentation Value (%d):\n”, c->redirecting_num_presentation_ind);
ss7_message(ss7, “\t\tRedirecting Screening Value (%d):\n”, c->redirecting_num_screening_ind);
}
}

a2598 12

void isup_set_redirectiong_info_reason(struct ss7 *ss7, struct isup_call *c, unsigned char redirect_info_ind, unsigned char redirect_info_orig_reas,
unsigned char redirect_info_counter, unsigned char redirect_info_reas)
{
c->redirect_info = 1;
c->redirect_info_ind = redirect_info_ind;
c->redirect_info_orig_reas = redirect_info_orig_reas;
c->redirect_info_counter = redirect_info_counter;
c->redirect_info_reas = redirect_info_reas;
}

a2603 5
void isup_set_redirection_counter(struct ss7 *ss7, struct isup_call *c, unsigned char redirect_counter)
{
c->redirect_counter = redirect_counter;
}

a3421 1
//return isup_event_iam(ss7, c, opc);
a3438 2
//e->rel.redirnum = c->redirecting_num;
//strncpy(e->rel.redirnum, c->redirecting_num, sizeof(e->rel.redirnum));
a4340 2
//int redirnum;

a4346 1
//ss7_message(ss7, “\t\tSS7 Cause Value For REL %s:\n”, cause);
a4349 1
//redirnum = cause;
a4350 1
//ss7_message(ss7, “\t\tRidirect number on REL (%s):\n”, redirnum);

isup.h

a125 1
#define ISUP_PARM_REDIRECTION_INFO_REASON 0x14
a134 1
#define ISUP_PARM_REDIRECTION_NUMBER 0x0c
a136 1
#define ISUP_PARM_REDIRECTION_COUNTER 0x78
a221 3
unsigned char rel_redirection_nai;
unsigned char rel_redirecting_num_nai;
char rel_redirecting_num[ISUP_MAX_NUM];
a246 1
int redirnum;

libss7.h
a215 2
unsigned char rel_redirection_nai;
unsigned char rel_redirecting_num_nai;
a241 1
char redirnum[50];
a577 2
void isup_set_redirection_number(struct ss7 *ss7, struct isup_call *c, const char *redirecting_number);

a580 3
void isup_set_redirectiong_info_reason(struct ss7 *ss7, struct isup_call *c, unsigned char redirect_info_ind, unsigned char redirect_info_orig_reas,
unsigned char redirect_info_counter, unsigned char redirect_info_reas);

a582 2
void isup_set_redirection_counter(struct ss7 *ss7, struct isup_call *c, unsigned char redirect_counter);

After Adding Patches recompile the both libss7 and asterisk.

Set the following Variables in Asterisk Dialplan as below.

exten => s,1,Set(_SS7_LSPI_IDENT=ON)
exten => s,2,Set(_SS7_SEND_FAR=1)
exten => s,3,Set(_SS7_RLT_ON=YES)
exten => s,4,Set(_SS7_REL_REDIRECTION_NUMBER=XXXXXXXXXXXX)
exten => s,5,set(_SS7_REL_REDIRECTION_COUNTER=1)
exten => s,6,set(_SS7_REL_REDIRECT_INFO_IND=1)
exten => s,7,set(_SS7_REL_REDIRECT_INFO_ORIG_REAS=0)
exten => s,8,set(_SS7_REL_REDIRECT_INFO_COUNTER=1)
exten => s,9,set(_SS7_REL_REDIRECT_INFO_REAS=0)
exten => s,10,set(_SS7_CAUSE=23)
exten => s,11,WaitExten(1)
exten => s,12,Hangup(23)

If you have created a patch to add a new feature, it is much better if you submit it through issues.asterisk.org. To do that you will need to prepare it as a unified diff, against the trunk version of Asterisk, sign the electronic licence grant to Digium and append the patch as a code contirbution.

The problem with providing a patch here is that Digium will not use it, as part of the official Asterisk code, as there is no traceability of a licence grant for them to use it in their Asterisk based products. Also, it introduces the risk that someone will try to submit it, or a derivative, to the official code themselves, even though they don’t have the legal right to make the licence grant.