Skip to content

Instantly share code, notes, and snippets.

@nomis
Last active April 21, 2024 09:13
Show Gist options
  • Select an option

  • Save nomis/b125c3885c937917078886fd4ad0f946 to your computer and use it in GitHub Desktop.

Select an option

Save nomis/b125c3885c937917078886fd4ad0f946 to your computer and use it in GitHub Desktop.

Revisions

  1. nomis revised this gist Apr 21, 2024. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions output.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    $ make LDLIBS=-lsctp sctp
    g++ sctp.cpp -lsctp -o sctp
    $ ./sctp
    flags 32896 assoc_id 0 stream 0 port 42417 len 20
    flags 32896 assoc_id 0 stream 0 port 49898 len 20
    flags 128 assoc_id 132 stream 0 port 42417 len 1 data o
    flags 128 assoc_id 132 stream 0 port 42417 len 2 data OO
    flags 128 assoc_id 134 stream 0 port 49898 len 1 data e
    flags 128 assoc_id 134 stream 0 port 49898 len 2 data EE
    flags 128 assoc_id 134 stream 0 port 49898 len 1 data e
    flags 128 assoc_id 134 stream 0 port 49898 len 2 data EE
    flags 128 assoc_id 132 stream 0 port 42417 len 1 data o
    flags 128 assoc_id 132 stream 0 port 42417 len 2 data OO
  2. nomis revised this gist Apr 21, 2024. No changes.
  3. nomis created this gist Apr 21, 2024.
    150 changes: 150 additions & 0 deletions sctp.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,150 @@
    #include <errno.h>
    #include <netinet/in.h>
    #include <netinet/sctp.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <unistd.h>

    #include <iostream>

    int main() {
    int si = -1;
    int so = -1;
    int se = -1;
    struct sockaddr_in ai{};
    struct sockaddr_in ao{};
    struct sockaddr_in ae{};
    struct sockaddr_in am{};
    socklen_t li = sizeof(ai);
    socklen_t lo = sizeof(ao);
    socklen_t le = sizeof(ae);
    socklen_t lm;
    pid_t pid = getpid();
    struct sctp_event_subscribe ei{};

    ai.sin_family = AF_INET;
    ai.sin_addr.s_addr = htonl(0x7F000000 | (pid & 0xFFFFFF));

    ao.sin_family = AF_INET;
    ao.sin_addr.s_addr = htonl(0x7F000000 | (pid & 0xFFFFFF));

    ae.sin_family = AF_INET;
    ae.sin_addr.s_addr = htonl(0x7F000000 | (pid & 0xFFFFFF));

    si = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
    if (si == -1) {
    perror("socket");
    return 1;
    }

    so = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
    if (so == -1) {
    perror("socket");
    return 1;
    }

    se = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
    if (se == -1) {
    perror("socket");
    return 1;
    }

    if (bind(si, reinterpret_cast<struct sockaddr*>(&ai), sizeof(ai)) == -1) {
    perror("bind");
    return 1;
    }

    if (bind(so, reinterpret_cast<struct sockaddr*>(&ao), sizeof(ao)) == -1) {
    perror("bind");
    return 1;
    }

    if (bind(se, reinterpret_cast<struct sockaddr*>(&ae), sizeof(ae)) == -1) {
    perror("bind");
    return 1;
    }

    if (getsockname(si, reinterpret_cast<struct sockaddr*>(&ai), &li) == -1) {
    perror("getsockname");
    return 1;
    }

    if (getsockname(so, reinterpret_cast<struct sockaddr*>(&ao), &lo) == -1) {
    perror("getsockname");
    return 1;
    }

    if (getsockname(se, reinterpret_cast<struct sockaddr*>(&ae), &le) == -1) {
    perror("getsockname");
    return 1;
    }

    ei.sctp_association_event = 1;
    ei.sctp_data_io_event = 1;

    if (setsockopt(si, IPPROTO_SCTP, SCTP_EVENTS, &ei, sizeof(ei)) == -1) {
    perror("setsockopt");
    return 1;
    }

    if (listen(si, 2) == -1) {
    perror("listen");
    return 1;
    }

    if (connect(so, reinterpret_cast<struct sockaddr*>(&ai), lo) == -1) {
    perror("connect");
    return 1;
    }

    if (connect(se, reinterpret_cast<struct sockaddr*>(&ai), le) == -1) {
    perror("connect");
    return 1;
    }

    write(so, "o", 1);
    write(so, "OO", 2);
    write(so, "o", 1);
    write(so, "OO", 2);
    write(se, "e", 1);
    write(se, "EE", 2);
    write(se, "e", 1);
    write(se, "EE", 2);

    while (true) {
    char buf[4096] = { 0 };
    struct sctp_sndrcvinfo info{};
    int flags;
    int len;

    lm = sizeof(am);
    flags = 0;

    len = sctp_recvmsg(si, buf, sizeof(buf), reinterpret_cast<struct sockaddr *>(&am), &lm, &info, &flags);
    if (len == -1) {
    perror("sctp_recvmsg");
    return 1;
    }

    std::cout
    << "flags " << flags
    << " assoc_id " << info.sinfo_assoc_id
    << " stream " << info.sinfo_stream
    << " port " << am.sin_port
    << " len " << len;

    if (!(flags & MSG_NOTIFICATION)) {
    if (len > 0)
    std::cout << " data ";

    for (int i = 0; i < len; i++ ) {
    std::cout << buf[i];
    }
    }

    std::cout << std::endl;
    }

    return 0;
    }