/*****************************************************************************

 @(#) $Id: test-sl.c,v 0.7.2.6 2001/02/03 05:49:00 brian Test $

 -----------------------------------------------------------------------------

 Copyright (C) 1997-2001  Brian Bidulock <bidulock@dallas.net>

 All Rights Reserved.

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 675 Mass
 Ave, Cambridge, MA 02139, USA.

 -----------------------------------------------------------------------------

 Last Modified $Date: 2001/02/03 05:49:00 $ by $Author: brian $

 *****************************************************************************/

static char const ident[] = "$Id: test-sl.c,v 0.7.2.6 2001/02/03 05:49:00 brian Test $";

/*
 *  This file is for testing the ss7-sdludp driver.
 */

#include <sys/stropts.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/poll.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <ss7/lmi.h>
#include <ss7/lmi_ioctl.h>
#include <ss7/devi.h>
#include <ss7/devi_ioctl.h>
#include <ss7/sdli.h>
#include <ss7/sdli_ioctl.h>
#include <ss7/sdti.h>
#include <ss7/sdti_ioctl.h>
#include <ss7/sli.h>
#include <ss7/sli_ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUFSIZE 272

typedef struct ppa {
    struct sockaddr_in loc;
    struct sockaddr_in rem;
} ppa_t;

void print_ppa(ppa_t *ppa) {
    printf("PPA loc Address family = %d\n", ppa->loc.sin_family);
    printf("PPA loc Port = %d\n", ppa->loc.sin_port);
    printf("PPA loc Address = %s\n", inet_ntoa(ppa->loc.sin_addr));
    printf("PPA rem Address family = %d\n", ppa->rem.sin_family);
    printf("PPA rem Port = %d\n", ppa->rem.sin_port);
    printf("PPA rem Address = %s\n", inet_ntoa(ppa->rem.sin_addr));
}

const char *lmi_strreason(unsigned int reason)
{
    const char *r;
    switch ( reason ) {
        default:
        case LMI_UNSPEC:         r = "Unknown or unspecified";                  break;
        case LMI_BADADDRESS:     r = "Address was invalid";                     break;
        case LMI_BADADDRTYPE:    r = "Invalid address type";                    break;
        case LMI_BADDIAL:        r = "(not used)";                              break;
        case LMI_BADDIALTYPE:    r = "(not used)";                              break;
        case LMI_BADDISPOSAL:    r = "Invalid disposal parameter";              break;
        case LMI_BADFRAME:       r = "Defective SDU received";                  break;
        case LMI_BADPPA:         r = "Invalid PPA identifier";                  break;
        case LMI_BADPRIM:        r = "Unregognized primitive";                  break;
        case LMI_DISC:           r = "Disconnected";                            break;
        case LMI_EVENT:          r = "Protocol-specific event ocurred";         break;
        case LMI_FATALERR:       r = "Device has become unusable";              break;
        case LMI_INITFAILED:     r = "Link initialization failed";              break;
        case LMI_NOTSUPP:        r = "Primitive not supported by this device";  break;
        case LMI_OUTSTATE:       r = "Primitive was issued from invalid state"; break;
        case LMI_PROTOSHORT:     r = "M_PROTO block too short";                 break;
        case LMI_SYSERR:         r = "UNIX system error";                       break;
        case LMI_WRITEFAIL:      r = "Unitdata request failed";                 break;
        case LMI_CRCERR:         r = "CRC or FCS error";                        break;
        case LMI_DLE_EOT:        r = "DLE EOT detected";                        break;
        case LMI_FORMAT:         r = "Format error detected";                   break;
        case LMI_HDLC_ABORT:     r = "Aborted frame detected";                  break;
        case LMI_OVERRUN:        r = "Input overrun";                           break;
        case LMI_TOOSHORT:       r = "Frame too short";                         break;
        case LMI_INCOMPLETE:     r = "Partial frame received";                  break;
        case LMI_BUSY:           r = "Telephone was busy";                      break;
        case LMI_NOANSWER:       r = "Connection went unanswered";              break;
        case LMI_CALLREJECT:     r = "Connection rejected";                     break;
        case LMI_HDLC_IDLE:      r = "HDLC line went idle";                     break;
        case LMI_HDLC_NOTIDLE:   r = "HDLC link no longer idle";                break;
        case LMI_QUIESCENT:      r = "Line being reassigned";                   break;
        case LMI_RESUMED:        r = "Line has been reassigned";                break;
        case LMI_DSRTIMEOUT:     r = "Did not see DSR in time";                 break;
        case LMI_LAN_COLLISIONS: r = "LAN excessive collisions";                break;
        case LMI_LAN_REFUSED:    r = "LAN message refused";                     break;
        case LMI_LAN_NOSTATION:  r = "LAN no such station";                     break;
        case LMI_LOSTCTS:        r = "Lost Clear to Send signal";               break;
        case LMI_DEVERR:         r = "Start of device-specific error codes";    break;
    }
    return r;
}

int test_getmsg(int fd) {
    int ret, flags;
    struct strbuf ctrl;
    struct strbuf data;
    char cbuf[BUFSIZE];
    char dbuf[BUFSIZE];
    union LMI_primitives *p = (union LMI_primitives *)cbuf;
    union SL_primitives *l = (union SL_primitives *)cbuf;

    ctrl.maxlen = BUFSIZE;
    ctrl.len    = 0;
    ctrl.buf    = cbuf;

    data.maxlen = BUFSIZE;
    data.len    = 0;
    data.buf    = dbuf;

    printf("\nAttempting getmsg\n");

    if ( (ret = getmsg(fd, &ctrl, &data, &flags)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        return(0);
    } else
        printf("Getmsg succeeded!\n");

    if ( ret == 0 ) {
        if ( ctrl.len > 0 ) {
            switch ( p->lmi_primitive ) {
                case LMI_INFO_ACK:
                    {
                        int ppalen = ctrl.len - sizeof(p->info_ack);
                        printf("LMI_INFO_ACK:\n");
                        printf("Version = 0x%08lx\n", p->info_ack.lmi_version);
                        printf("State = %lu\n", p->info_ack.lmi_state);
                        printf("Max sdu = %lu\n", p->info_ack.lmi_max_sdu);
                        printf("Min sdu = %lu\n", p->info_ack.lmi_min_sdu);
                        printf("Header len = %lu\n", p->info_ack.lmi_header_len);
                        printf("PPA style = %lu\n", p->info_ack.lmi_ppa_style);
                        printf("PPA length = %u\n", ppalen);
                        print_ppa((ppa_t *)p->info_ack.lmi_ppa_addr);
                    }
                    return(p->lmi_primitive);
                case LMI_OK_ACK:
                    {
                        printf("LMI_OK_ACK:\n");
                        printf("Correct primitive = %lu\n", p->ok_ack.lmi_correct_primitive);
                        printf("State = %lu\n", p->ok_ack.lmi_state);
                    }
                    return(p->lmi_primitive);
                case LMI_ERROR_ACK:
                    {
                        printf("LMI_ERROR_ACK:\n");
                        printf("Error number = %lu\n", p->error_ack.lmi_errno);
                        printf("Error string = %s\n", strerror(p->error_ack.lmi_errno));
                        printf("Reason number = %lu\n", p->error_ack.lmi_reason);
                        printf("Reason string = %s\n", lmi_strreason(p->error_ack.lmi_reason));
                        printf("Error primitive = %lu\n", p->error_ack.lmi_error_primitive);
                        printf("State = %lu\n", p->error_ack.lmi_state);
                    }
                    return(p->lmi_primitive);
                case LMI_ERROR_IND:
                    {
                        printf("LMI_ERROR_IND:\n");
                        printf("Error number = %lu\n", p->error_ind.lmi_errno);
                        printf("Error string = %s\n", strerror(p->error_ind.lmi_errno));
                        printf("Reason number = %lu\n", p->error_ind.lmi_reason);
                        printf("Reason string = %s\n", lmi_strreason(p->error_ind.lmi_reason));
                        printf("State = %lu\n", p->error_ind.lmi_state);
                    }
                    return(p->lmi_primitive);
                case LMI_ENABLE_CON:
                    {
                        printf("LMI_ENABLE_CON:\n");
                        printf("State = %lu\n", p->enable_con.lmi_state);
                    }
                    return(p->lmi_primitive);
                case LMI_DISABLE_CON:
                    {
                        printf("LMI_DISABLE_CON:\n");
                        printf("State = %lu\n", p->enable_con.lmi_state);
                    }
                    return(p->lmi_primitive);
                default:
                    switch ( l->sl_primitive ) {
                        case SL_PDU_IND:
                            {
                                int i; char *c = dbuf;
                                printf("SL_PDU_IND:\n");
                                printf("  Data: ");
                                for ( i=0; i<data.len; i++, c++ ) printf("%02x",*c);
                                printf("\n");
                            }
                            return(l->sl_primitive);
                        case SL_LINK_CONGESTED_IND:
                            {
                                printf("SL_LINK_CONGESTED_IND:\n");
                                printf("  timestamp = %lu\n", l->link_cong_ind.sl_timestamp);
                                printf("  cong stat = %lu\n", l->link_cong_ind.sl_cong_level);
                                printf("  disc stat = %lu\n", l->link_cong_ind.sl_disc_level);
                            }
                            return(l->sl_primitive);
                        case SL_LINK_CONGESTION_CEASED_IND:
                            {
                                printf("SL_LINK_CONGESTION_CEASED_IND:\n");
                                printf("  timestamp = %lu\n", l->link_cong_ceased_ind.sl_timestamp);
                                printf("  cong stat = %lu\n", l->link_cong_ceased_ind.sl_cong_level);
                                printf("  disc stat = %lu\n", l->link_cong_ceased_ind.sl_disc_level);
                            }
                            return(l->sl_primitive);
                        case SL_RETRIEVED_MESSAGE_IND:
                            {
                                int i; char *c = dbuf;
                                printf("SL_RETRIEVED_MESSAGE_IND:\n");
                                printf("  Data: ");
                                for ( i=0; i<data.len; i++, c++ ) printf("%02x",*c);
                                printf("\n");
                            }
                            return(l->sl_primitive);
                        case SL_RB_CLEARED_IND:
                            {
                                printf("SL_RB_CLEARED_IND\n");
                            }
                            return(l->sl_primitive);
                        case SL_BSNT_IND:
                            {
                                printf("SL_BSNT_IND:\n");
                                printf("  bsnt = %lu\n", l->bsnt_ind.sl_bsnt);
                            }
                            return(l->sl_primitive);
                        case SL_IN_SERVICE_IND:
                            {
                                printf("SL_IN_SERVICE_IND\n");
                            }
                            return(l->sl_primitive);
                        case SL_OUT_OF_SERVICE_IND:
                            {
                                printf("SL_OUT_OF_SERVICE_IND:\n");
                                printf("  timestamp = %lu\n", l->out_of_service_ind.sl_timestamp);
                                printf("  reason    = %lu\n", l->out_of_service_ind.sl_reason);
                            }
                            return(l->sl_primitive);
                        case SL_REMOTE_PROCESSOR_OUTAGE_IND:
                            {
                                printf("SL_REMOTE_PROCESSOR_OUTAGE_IND:\n");
                                printf("  timestamp = %lu\n", l->rem_proc_out_ind.sl_timestamp);
                            }
                            return(l->sl_primitive);
                        case SL_REMOTE_PROCESSOR_RECOVERED_IND:
                            {
                                printf("SL_REMOTE_PROCESSOR_RECOVERED_IND:\n");
                                printf("  timestamp = %lu\n", l->rem_proc_recovered_ind.sl_timestamp);
                            }
                            return(l->sl_primitive);
                        case SL_RTB_CLEARED_IND:
                            {
                                printf("SL_RTB_CLEARED_IND\n");
                            }
                            return(l->sl_primitive);
                        default:
                            {
                                printf("Unrecognized primitive %lu!\n", l->sl_primitive);
                            }
                            return(l->sl_primitive);
                    }
            }
        }
    }
    return (0);
}

void test_info_req(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union LMI_primitives *p = (union LMI_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->info_req);
    ctrl.buf    = cbuf;
    p->lmi_primitive = LMI_INFO_REQ;
    printf("\nAttempting info request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_attach_req(int fd, ppa_t *ppap) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union LMI_primitives *p = (union LMI_primitives *)cbuf;

    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->attach_req)+sizeof(ppa_t);
    ctrl.buf    = cbuf;
    p->attach_req.lmi_primitive = LMI_ATTACH_REQ;
    bcopy(ppap, p->attach_req.lmi_ppa, sizeof(ppa_t));
    printf("\nAttempting attach request\n");
    print_ppa((ppa_t *)p->attach_req.lmi_ppa);
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_detach_req(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union LMI_primitives *p = (union LMI_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->detach_req);
    ctrl.buf    = cbuf;
    p->lmi_primitive = LMI_DETACH_REQ;
    printf("\nAttempting detach request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_enable_req(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union LMI_primitives *p = (union LMI_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->enable_req);
    ctrl.buf    = cbuf;
    p->lmi_primitive = LMI_ENABLE_REQ;
    printf("\nAttempting enable request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_disable_req(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union LMI_primitives *p = (union LMI_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->disable_req);
    ctrl.buf    = cbuf;
    p->lmi_primitive = LMI_DISABLE_REQ;
    printf("\nAttempting disable request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

int test_open(void) {
    int fd;
    printf("\nAttempting to open ss7-sdludp0\n");
    if ( (fd = open("/dev/ss7-sdludp0",O_NONBLOCK|O_RDWR)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Open succeeded!\n");
    return(fd);
}

void test_push(int fd) {
    int ret;
    printf("\nAttempting to push streams-sdt\n");
    if ( (ret = ioctl(fd, I_PUSH, "sdt")) < 0 ) {
        printf("return = %d\n", ret);
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Push succeeded!\n");
    printf("\nAttempting to push streams-sl\n");
    if ( (ret = ioctl(fd, I_PUSH, "sl")) < 0 ) {
        printf("return = %d\n", ret);
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Push succeeded!\n");
}

void test_close(int fd) {
    int ret;
    printf("\nAttempting to close ss7-sdludp0\n");
    if ( (ret = close(fd)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Close succeeded!\n");
}

void test_write(int fd) {
    const char buf[] = "Hello World!";
    int i;
    int ret;
    for ( i=0; i<10; i++ ) {
        printf("\nAttempting write\n");
        ret = write(fd, buf, 13);
        if ( ret < 0 ) {
            printf("error = %d\n", errno);
            perror(__FUNCTION__);
            exit(2);
        } else
            printf("Write succeeded, wrote %d bytes!\n", ret);
    }
}

void test_daedt_start(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union SDT_primitives *p = (union SDT_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->daedt_start_req);
    ctrl.buf    = cbuf;
    p->sdt_primitive = SDT_DAEDT_START_REQ;
    printf("\nAttempting DAEDT start request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_daedr_start(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union SDT_primitives *p = (union SDT_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->daedr_start_req);
    ctrl.buf    = cbuf;
    p->sdt_primitive = SDT_DAEDR_START_REQ;
    printf("\nAttempting DAEDR start request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_power_on(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union SL_primitives *p = (union SL_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->power_on_req);
    ctrl.buf    = cbuf;
    p->sl_primitive = SL_POWER_ON_REQ;
    printf("\nAttempting LSC Power On request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_start(int fd) {
    int ret;
    struct strbuf ctrl;
    char cbuf[BUFSIZE];
    union SL_primitives *p = (union SL_primitives *)cbuf;
    ctrl.maxlen = BUFSIZE;
    ctrl.len    = sizeof(p->start_req);
    ctrl.buf    = cbuf;
    p->sl_primitive = SL_START_REQ;
    printf("\nAttempting Link Start request\n");
    if ( (ret = putmsg(fd, &ctrl, NULL, RS_HIPRI)) < 0 ) {
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    } else
        printf("Putmsg succeeded!\n");
    while ( test_getmsg(fd) );
}

void test_read(int fd) {
    char buf[256];
    int i, ret;
    i = 0;
    printf("\nAttempting read\n");
    for (;;) {
        ret = read(fd, buf, 256);
        if ( ret < 0 ) {
            if ( errno == EAGAIN ) {
                if ( i++ < 100 )
                    continue;
            }
            printf("error = %d\n", errno);
            perror(__FUNCTION__);
            break;
        } else
            printf("Read succeeded, read %d bytes!\n", ret);
        if ( ret > 0 ) {
            int i;
            char *c = (char *)buf;
            printf("Message[%d]: ", ret);
            for ( i=0; i<ret; i++, c++ )
                printf("%c", *c);
            printf("\n");
        }
    }
}

int test_ioctl(int fd, int cmd, void *arg, int len) {
    struct strioctl ctl = { cmd, 0, len, arg };
    int ret;
    ret = ioctl(fd, I_STR, &ctl);
    if ( ret < 0 ) {
        printf("return = %d\n", ret);
        printf("error = %d\n", errno);
        perror(__FUNCTION__);
        exit(2);
    }
    return ctl.ic_len;
}

void test_ioctls(int fd) {
    unsigned char buf[256];
    sdl_config_t *c = (sdl_config_t *)buf;
    sdl_statem_t *s = (sdl_statem_t *)buf;
    printf("\nAttempting ioctls\n");
    test_ioctl(fd, SDL_IOCGCONFIG, buf, sizeof(sdl_config_t));
    printf("Config:\n");
    printf("  N = %lu\n", c->N);
    printf("  m = %lu\n", c->m);
    test_ioctl(fd, SDL_IOCGSTATEM, buf, sizeof(sdl_statem_t));
    printf("State:\n");
    printf("  daedt_state = %lu\n", s->daedt_state);
    printf("  daedr_state = %lu\n", s->daedr_state);
    printf("  octet_counting_mode = %lu\n", s->octet_counting_mode);
    printf("Iface:\n");
    test_ioctl(fd, DEV_IOCGIFFLAGS, buf, sizeof(unsigned long));
    printf("  ifflags = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGIFTYPE, buf, sizeof(unsigned long));
    printf("  iftype = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGGRPTYPE, buf, sizeof(unsigned long));
    printf("  ifgtype = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGIFMODE, buf, sizeof(unsigned long));
    printf("  ifmode = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGIFRATE, buf, sizeof(unsigned long));
    printf("  ifrate = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGIFCLOCK, buf, sizeof(unsigned long));
    printf("  ifclock = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGIFCODING, buf, sizeof(unsigned long));
    printf("  ifcoding = %lu\n", *((unsigned long *)buf));
    test_ioctl(fd, DEV_IOCGIFLEADS, buf, sizeof(unsigned long));
    printf("  ifleads = %lu\n", *((unsigned long *)buf));
}

void test_config(int fd) {
    unsigned char buf[sizeof(sl_config_t)];
    lmi_option_t *opt  = (lmi_option_t *)buf;
    sl_config_t  *slc  = (sl_config_t  *)buf;
    sdt_config_t *sdtc = (sdt_config_t *)buf;
    sdl_config_t *sdlc = (sdl_config_t *)buf;
    printf("\nAttempting set option\n");
    opt->pvar = SS7_PVAR_ITUT_88;
    opt->popt = SS7_POPT_MPLEV | SS7_POPT_HSL | SS7_POPT_XSN;
    test_ioctl(fd, SDL_IOCSOPTIONS, buf, sizeof(*opt));
    test_ioctl(fd, SDT_IOCSOPTIONS, buf, sizeof(*opt));
    test_ioctl(fd, SL_IOCSOPTIONS,  buf, sizeof(*opt));

    printf("SDL config:\n");
    sdlc->N = 16;
    sdlc->m = 272;
    test_ioctl(fd, SDL_IOCSCONFIG, buf, sizeof(*sdlc));
    test_ioctl(fd, SDL_IOCGCONFIG, buf, sizeof(*sdlc));
    printf("  N = %lu\n", sdlc->N);
    printf("  m = %lu\n", sdlc->m);

#ifndef HZ
#define HZ 100
#endif

    printf("SDT config:\n");
    sdtc->t8 = 100*HZ/1000; /* jiffies */
    sdtc->Tin = 4;
    sdtc->Tie = 1;
    sdtc->T = 64;
    sdtc->D = 256;
    sdtc->Te = 577169;
    sdtc->De = 9308000;
    sdtc->Ue = 144292000;
    test_ioctl(fd, SDT_IOCSCONFIG, buf, sizeof(*sdtc));
    test_ioctl(fd, SDT_IOCGCONFIG, buf, sizeof(*sdtc));
    printf("  t8 = %lu\n", sdtc->t8);
    printf("  Tin = %lu\n", sdtc->Tin);
    printf("  Tie = %lu\n", sdtc->Tie);
    printf("  T = %lu\n", sdtc->T);
    printf("  D = %lu\n", sdtc->D);
    printf("  Te = %lu\n", sdtc->Te);
    printf("  De = %lu\n", sdtc->De);
    printf("  Ue = %lu\n", sdtc->Ue);

    printf("SL config:\n");
    slc->t1 = 300*HZ;       /* jiffies */
    slc->t2 = 50*HZ;        /* jiffies */
    slc->t2l = 20*HZ;       /* jiffies */
    slc->t2h = 100*HZ;      /* jiffies */
    slc->t3 = 1*HZ;         /* jiffies */
    slc->t4n = 30*HZ;       /* jiffies */
    slc->t4e = 500*HZ/1000; /* jiffies */
    slc->t5 = 100*HZ/1000;  /* jiffies */
    slc->t6 = 3*HZ;         /* jiffies */
    slc->t7 = 500*HZ/1000;  /* jiffies */
    slc->rb_abate   = 3;    /* messages */
    slc->rb_accept  = 6;    /* messages */
    slc->rb_discard = 9;    /* messages */
    slc->tb_abate_1 = 1*272;    /* octets */
    slc->tb_onset_1 = 2*272;    /* octets */
    slc->tb_discd_1 = 3*272;    /* octets */
    slc->tb_abate_2 = 4*272;    /* octets */
    slc->tb_onset_2 = 5*272;    /* octets */
    slc->tb_discd_2 = 6*272;    /* octets */
    slc->tb_abate_3 = 7*272;    /* octets */
    slc->tb_onset_3 = 8*272;    /* octets */
    slc->tb_discd_3 = 9*272;    /* octets */
    slc->N1 = 127;  /* messages */
    slc->N2 = 1000; /* octets */
    slc->M = 5;
    test_ioctl(fd, SL_IOCSCONFIG,  buf, sizeof(*slc));
    printf("  t1 = %lu\n", slc->t1);
    printf("  t2 = %lu\n", slc->t2);
    printf("  t2l = %lu\n", slc->t2l);
    printf("  t2h = %lu\n", slc->t2h);
    printf("  t3 = %lu\n", slc->t3);
    printf("  t4n = %lu\n", slc->t4n);
    printf("  t4e = %lu\n", slc->t4e);
    printf("  t5 = %lu\n", slc->t5);
    printf("  t6 = %lu\n", slc->t6);
    printf("  t7 = %lu\n", slc->t7);
    printf("  rb_abate = %lu\n", slc->rb_abate);
    printf("  rb_accept = %lu\n", slc->rb_accept);
    printf("  rb_discard = %lu\n", slc->rb_discard);
    printf("  tb_abate_1 = %lu\n", slc->tb_abate_1);
    printf("  tb_onset_1 = %lu\n", slc->tb_onset_1);
    printf("  tb_abate_1 = %lu\n", slc->tb_discd_1);
    printf("  tb_abate_2 = %lu\n", slc->tb_abate_2);
    printf("  tb_onset_2 = %lu\n", slc->tb_onset_2);
    printf("  tb_abate_2 = %lu\n", slc->tb_discd_2);
    printf("  tb_abate_3 = %lu\n", slc->tb_abate_3);
    printf("  tb_onset_3 = %lu\n", slc->tb_onset_3);
    printf("  tb_abate_3 = %lu\n", slc->tb_discd_3);
    printf("  N1 = %lu\n", slc->N1);
    printf("  N2 = %lu\n", slc->N2);
    printf("  M = %lu\n", slc->M);
}

int main () {
    int fd1, fd2;
    ppa_t ppa1, ppa2;
    printf("Simple test program for ss7-sdludp driver.\n");

    ppa1.loc.sin_family = AF_INET;
    ppa1.loc.sin_port = 10000;
    ppa1.loc.sin_addr.s_addr = INADDR_ANY;
    ppa1.rem.sin_family = AF_INET;
    ppa1.rem.sin_port = 10001;
    inet_aton("127.0.0.1",&ppa1.rem.sin_addr);

    ppa2.loc.sin_family = AF_INET;
    ppa2.loc.sin_port = 10001;
    ppa2.loc.sin_addr.s_addr = INADDR_ANY;
    ppa2.rem.sin_family = AF_INET;
    ppa2.rem.sin_port = 10000;
    inet_aton("127.0.0.1",&ppa2.rem.sin_addr);

    fd1 = test_open();
    fd2 = test_open();

    ioctl(fd1, I_SRDOPT, RMSGD);
    ioctl(fd2, I_SRDOPT, RMSGD);

    test_push(fd1);
    test_push(fd2);

    test_info_req(fd1);
    test_attach_req(fd1, &ppa1);
    test_info_req(fd1);
    test_enable_req(fd1);
    test_info_req(fd1);

    test_info_req(fd2);
    test_attach_req(fd2, &ppa2);
    test_info_req(fd2);
    test_enable_req(fd2);
    test_info_req(fd2);

    test_ioctls(fd1);

//  test_daedt_start(fd1);
//  test_daedr_start(fd1);
//  test_daedt_start(fd2);
//  test_daedr_start(fd2);

    test_ioctls(fd2);

    test_config(fd1);
    test_config(fd2);

    test_power_on(fd1);
    test_power_on(fd2);

    sleep(3);

    test_start(fd1);
    test_start(fd2);

    {
        int prim1 = 0, prim2 = 0;
        int i = 400;
        while ( --i ) {
            if ( prim1 != SL_IN_SERVICE_IND && prim1 != SL_OUT_OF_SERVICE_IND )
                prim1 = test_getmsg(fd1);
            if ( prim2 != SL_IN_SERVICE_IND && prim2 != SL_OUT_OF_SERVICE_IND )
                prim2 = test_getmsg(fd2);
            if ( ( prim1 == SL_IN_SERVICE_IND || prim1 == SL_OUT_OF_SERVICE_IND ) &&
                 ( prim2 == SL_IN_SERVICE_IND || prim2 == SL_OUT_OF_SERVICE_IND ) )
                break;
            sleep(1);
        }
    }

//  test_write(fd1);

//  while ( test_getmsg(fd1) );
//  while ( test_getmsg(fd2) );
    
//  test_read(fd2);

    test_disable_req(fd1);
    test_info_req(fd1);
    test_detach_req(fd1);
    test_info_req(fd1);

    test_disable_req(fd2);
    test_info_req(fd2);
    test_detach_req(fd2);
    test_info_req(fd2);

    test_close(fd1);
    test_close(fd2);

    printf("Done.\n");

    return(0);
}
