| /* $Header: /usr/sctpCVS/APPS/user/userInputModule.c,v 1.115 2011-08-09 18:40:43 randall Exp $ */ |
| |
| /* |
| * Copyright (C) 2002-2006 Cisco Systems Inc, |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the project nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| /* Parser for user commands. |
| * |
| * Support for command completion and history added by |
| * Marco Molteni <mmolteni@cisco.com>. |
| */ |
| #if defined(__FreeBSD__) || defined(__APPLE__) |
| #define __BSD_SCTP_STACK__ |
| #else |
| /* Solaris: old API */ |
| #define SCTP_EOF MSG_EOF |
| #define SCTP_ABORT MSG_ABORT |
| #define SCTP_UNORDERED MSG_UNORDERED |
| /* unsupported send flags */ |
| #define SCTP_PR_SCTP_TTL 0 |
| #define SCTP_PR_SCTP_BUF 0 |
| #define SCTP_PR_SCTP_RXT 0 |
| #define SCTP_ADDR_OVER 0 |
| #define SCTP_SENDALL 0 |
| #endif |
| |
| #include <userInputModule.h> |
| |
| #include <distributor.h> |
| #include <ctype.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/sysctl.h> |
| #include <stdint.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #ifndef linux |
| #include <net/if_dl.h> |
| #include <sys/filio.h> |
| #endif |
| #include <sys/ioctl.h> |
| #include <sys/stat.h> |
| #include <stdarg.h> |
| #include <signal.h> |
| #include <fcntl.h> |
| #include <time.h> |
| #include <string.h> |
| #include <net/if.h> |
| #include <errno.h> |
| #include <poll.h> |
| #include <sys/uio.h> |
| |
| /* These should not be included except for our test |
| * module to generate TLV's to dump in the REL-REQ |
| */ |
| /* Line editing. */ |
| #include <readline/readline.h> |
| #include <readline/history.h> |
| #include <netinet/sctp.h> |
| |
| #if defined(__BSD_SCTP_STACK__) |
| #include <netinet/sctp_uio.h> |
| #endif |
| #include <printMessageHandler.h> |
| |
| static int execute_line(const char *line); |
| static char *command_generator(char *text, int state); |
| |
| int block_mode = 1; |
| int loop_sleep = 0; |
| |
| /* Line editing. |
| * Each command must have its own function, with the prefix "cmd_". |
| */ |
| static int cmd_setloopsleep(char *argv[], int argc); |
| static int cmd_settos(char *argv[], int argc); |
| static int cmd_getloopsleep(char *argv[], int argc); |
| static int cmd_abort(char *argv[], int argc); |
| static int cmd_abortassoc(char *argv[], int argc); |
| static int cmd_addip(char *argv[], int argc); |
| static int cmd_assoc(char *argv[], int argc); |
| static int cmd_bindx(char *argv[], int argc); |
| static int cmd_bulk(char *argv[], int argc); |
| static int cmd_bulkstat(char *argv[], int argc); |
| static int cmd_chgcookielife(char *argv[], int argc); |
| static int cmd_xconnect(char *argv[], int argc); |
| static int cmd_continual(char *argv[], int argc); |
| static int cmd_cwndlog(char *argv[], int argc); |
| static int cmd_clrcwndlog(char *argv[], int argc); |
| static int cmd_defretryi(char *argv[], int argc); |
| static int cmd_defretrys(char *argv[], int argc); |
| static int cmd_defrwnd(char *argv[], int argc); |
| static int cmd_delip(char *argv[], int argc); |
| static int cmd_doheartbeat(char *argv[], int argc); |
| static int cmd_getblocking(char *argv[], int argc); |
| static int cmd_getcurcookielife(char *argv[], int argc); |
| static int cmd_getcwndpost(char *argv[], int argc); |
| static int cmd_getdefcookielife(char *argv[], int argc); |
| static int cmd_gethbdelay(char *argv[], int argc); |
| static int cmd_getstat(char *argv[], int argc); |
| static int cmd_clrstat(char *argv[], int argc); |
| static int cmd_getassocstat(char *argv[], int argc); |
| static int cmd_addstreams(char *argv[], int argc); |
| |
| static int cmd_getprimary(char *argv[], int argc); |
| static int cmd_getrtt(char *argv[], int argc); |
| static int cmd_getsnd(char *argv[], int argc); |
| static int cmd_heart(char *argv[], int argc); |
| static int cmd_heartdelay(char *argv[], int argc); |
| static int cmd_help(char *argv[], int argc); |
| static int cmd_hulkstart(char *argv[], int argc); |
| static int cmd_hulkstop(char *argv[], int argc); |
| static int cmd_bulkstop(char *argv[], int argc); |
| static int cmd_initmultping(char *argv[], int argc); |
| static int cmd_inqueue(char *argv[], int argc); |
| static int cmd_multping(char *argv[], int argc); |
| static int cmd_netstats(char *argv[], int argc); |
| static int cmd_ping(char *argv[], int argc); |
| static int cmd_quit(char *argv[], int argc); |
| static int cmd_rftp(char *argv[], int argc); |
| static int cmd_printrftpstat(char *argv[], int argc); |
| static int cmd_rwnd(char *argv[], int argc); |
| static int cmd_sctpsendx(char *argv[], int argc); |
| static int cmd_send(char *argv[], int argc); |
| static int cmd_sendasoc(char *argv[], int argc); |
| static int cmd_getmaxburst(char *argv[], int argc); |
| static int cmd_setmaxburst(char *argv[], int argc); |
| static int cmd_sendloop(char *argv[], int argc); |
| static int cmd_sendloopend(char *argv[], int argc); |
| static int cmd_sendreltlv(char *argv[], int argc); |
| static int cmd_setbulkmode(char *argv[], int argc); |
| static int cmd_setdefcookielife(char *argv[], int argc); |
| static int cmd_setdefstream(char *argv[], int argc); |
| static int cmd_getfragmentation(char *argv[], int argc); |
| static int cmd_setfragmentation(char *argv[], int argc); |
| static int cmd_getautoclose(char *argv[], int argc); |
| static int cmd_setautoclose(char *argv[], int argc); |
| static int cmd_seterr(char *argv[], int argc); |
| static int cmd_sethost(char *argv[], int argc); |
| static int cmd_setinittsn(char *argv[], int argc); |
| static int cmd_getinittsn(char *argv[], int argc); |
| static int cmd_sethost6(char *argv[], int argc); |
| static int cmd_setneterr(char *argv[], int argc); |
| static int cmd_setopts(char *argv[], int argc); |
| static int cmd_setpay(char *argv[], int argc); |
| static int cmd_setport(char *argv[], int argc); |
| static int cmd_setprimary(char *argv[], int argc); |
| static int cmd_setautoasconf(char *argv[], int argc); |
| static int cmd_getautoasconf(char *argv[], int argc); |
| static int cmd_setremprimary(char *argv[], int argc); |
| static int cmd_setscope(char *argv[], int argc); |
| static int cmd_setstreams(char *argv[], int argc); |
| static int cmd_startmultping(char *argv[], int argc); |
| static int cmd_setadaption(char *argv[], int argc); |
| static int cmd_setblocking(char *argv[], int argc); |
| static int cmd_getadaption(char *argv[], int argc); |
| static int cmd_tella(char *argv[], int argc); |
| static int cmd_term(char *argv[], int argc); |
| static int cmd_whereto(char *argv[], int argc); |
| static int cmd_getpcbinfo(char *argv[], int argc); |
| static int cmd_getrtomin(char *argv[], int argc); |
| static int cmd_setrtomin(char *argv[], int argc); |
| static int cmd_getinitparam(char *argv[], int argc); |
| static int cmd_setinitparam(char *argv[], int argc); |
| static int cmd_gettimetolive(char *argv[], int argc); |
| static int cmd_settimetolive(char *argv[], int argc); |
| static int cmd_getlocaladdrs(char *argv[], int argc); |
| static int cmd_getassocids(char *argv[], int argc); |
| static int cmd_restorefd(char *argv[], int argc); |
| static int cmd_listen(char *argv[], int argc); |
| static int cmd_setfd(char *argv[], int argc); |
| static int cmd_getevents(char *argv[], int argc); |
| static int cmd_getpaddrs(char *argv[], int argc); |
| static int cmd_getstatus(char *argv[], int argc); |
| static int cmd_closefd(char *argv[], int argc); |
| static int cmd_silent(char *argv[], int argc); |
| static int cmd_silentcnt(char *argv[], int argc); |
| static int cmd_streamreset(char *argv[], int argc); |
| static int cmd_deliverydump(char *argv[], int argc); |
| static int cmd_sendsent(char *argv[], int argc); |
| static int cmd_getroute(char *argv[], int argc); |
| static int cmd_sendN(char *argv[], int argc); |
| |
| |
| static int cmd_savepacketlog(char *argv[], int argc); |
| |
| |
| static int cmd_setpdapi(char *argv[], int argc); |
| static int cmd_getpdapi(char *argv[], int argc); |
| |
| static int cmd_seteeor(char *argv[], int argc); |
| static int cmd_geteeor(char *argv[], int argc); |
| |
| |
| |
| static int cmd_getmaxseg(char *argv[], int argc); |
| static int cmd_setmaxseg(char *argv[], int argc); |
| |
| static int cmd_getnodelay(char *argv[], int argc); |
| static int cmd_setnodelay(char *argv[], int argc); |
| |
| static int cmd_getmsdelay(char *argv[], int argc); |
| static int cmd_setmsdelay(char *argv[], int argc); |
| |
| static int cmd_getv4mapped(char *argv[], int argc); |
| static int cmd_setv4mapped(char *argv[], int argc); |
| |
| static int cmd_addauth(char *argv[], int argc); |
| static int cmd_addkey(char *argv[], int argc); |
| static int cmd_addnullkey(char *argv[], int argc); |
| static int cmd_deactivatekey(char *argv[], int argc); |
| static int cmd_deletekey(char *argv[], int argc); |
| static int cmd_setactivekey(char *argv[], int argc); |
| static int cmd_getactivekey(char *argv[], int argc); |
| static int cmd_sethmac(char *argv[], int argc); |
| static int cmd_gethmac(char *argv[], int argc); |
| static int cmd_getlocalauth(char *argv[], int argc); |
| static int cmd_getpeerauth(char *argv[], int argc); |
| |
| static int cmd_setdebug(char *argv[], int argc); |
| |
| #ifndef SCTP_NO_TCP_MODEL |
| static int cmd_peeloff(char *argv[], int argc); |
| #endif /* !SCTP_NO_TCP_MODEL */ |
| |
| /* Line editing. */ |
| typedef int f2(char **, int); |
| |
| struct command { |
| char *co_name; /* Command name. */ |
| char *co_desc; /* Command description. */ |
| f2 *co_func; /* Function to call to execute the command. */ |
| }; |
| static int msdelaymode = 0; |
| |
| static int silent_mode = 0; |
| static unsigned int silent_count = 0; |
| static time_t time_started; |
| /* Line editing. |
| * Store the commands and the help descriptions. |
| * Please keep this list sorted in alphabetical order. |
| */ |
| static struct command commands[] = { |
| {"abort", "abort - abort the existing association", |
| cmd_abort}, |
| {"abortasoc", "abortasoc id - abort the asoc with given id", |
| cmd_abortassoc}, |
| {"addip", "addip address how - add ip address where how is the mask/action to pass\n" |
| " SCTP_ACTION_UPDATE_ALL_ASSOC=0x1\n" |
| " SCTP_ACTION_UPDATE_ENDPOINT=0x02\n" |
| " SCTP_ACTION_UPDATE_ONLY_ASSOC=0x04\n" |
| " SCTP_ACTION_QUEUE_REQUEST_ONLY=0x08\n" |
| " (which can all be or'd together if you want)", |
| cmd_addip}, |
| {"addstream", "addstream number - add more streams", |
| cmd_addstreams }, |
| {"assoc", "assoc - associate with the set destination", |
| cmd_assoc}, |
| {"bindx", "bindx type address - add/delete address to the endpoint\n" |
| " type: 0=add, 1=delete\n", |
| cmd_bindx}, |
| {"bulk", "bulk size stream count - send a bulk of messages", |
| cmd_bulk}, |
| { "bulkc", "bulkc size stream count - ", |
| cmd_sendN}, |
| |
| {"bulkstat", "bulkstat - display count of bulk packets and sent (seen resets)", |
| cmd_bulkstat}, |
| {"bulkstop", "bulkstop - stop the bulk transfer", |
| cmd_bulkstop}, |
| |
| {"chgcookielife", "chgcookielife val - change the current assoc cookieLife", |
| cmd_chgcookielife}, |
| {"closefd", "closefd fd# - close the tcp connected fd", |
| cmd_closefd}, |
| {"connectx", "connectx addr [addr's] - associate to the list of addresses\n", |
| cmd_xconnect}, |
| |
| {"continual", "continual num - set continuous init to num times", |
| cmd_continual}, |
| {"cwndlog", "cwndlog - get cwnd log", |
| cmd_cwndlog}, |
| {"clrcwndlog", "clrcwndlog - clear cwnd log", |
| cmd_clrcwndlog}, |
| |
| {"defretryi", "defretryi num - set a new association failure threshold for initing", |
| cmd_defretryi}, |
| {"defretrys", "defretrys num - set a new association failure threshold for sending", |
| cmd_defretrys}, |
| {"defrwnd", "defrwnd num - set the default rwnd of the SCTP", |
| cmd_defrwnd}, |
| {"delip", "delip address [how] - delete ip address where how is the mask/action to pass", |
| cmd_delip}, |
| {"doheartbeat", "doheartbeat - preform a on demand HB", |
| cmd_doheartbeat}, |
| {"getautoasconf", "getautoasconf current auto-asconf setting\n", |
| cmd_getautoasconf}, |
| {"getautoclose", "getautoclose - get autoclose value", |
| cmd_getautoclose}, |
| {"getblocking", "get blocking/non-blocking state (FIONBIO)", |
| cmd_getblocking}, |
| {"getcurcookielife", "getcurcookielife - display current assoc cookieLife", |
| cmd_getcurcookielife}, |
| {"getcwndpost", "getcwndpost - display cwnd post information collected", |
| cmd_getcwndpost}, |
| {"getdefcookielife", "getdefcookielife - display default cookie life", |
| cmd_getdefcookielife}, |
| {"getevents", "getevents - display the event registration status", |
| cmd_getevents}, |
| {"getpaddrs", "getpaddrs [asocid] - display the peers addresses", |
| cmd_getpaddrs}, |
| |
| {"getpdapi", "getpdapi - display the partual delivery point", |
| cmd_getpdapi}, |
| |
| {"geteeor", "geteeor - display the current Explicit EOR setting", |
| cmd_geteeor}, |
| |
| |
| |
| {"getstatus", "getstatus - display the association status", |
| cmd_getstatus}, |
| |
| |
| |
| {"heartctl", "heartctl on/off/allon/alloff - Turn HB on or off to the destination or all dests", |
| cmd_heart}, |
| {"getasocids", "getasocids - list all association id's", |
| cmd_getassocids}, |
| {"gethbdelay", "gethbdelay [ep] - get the hb delay", |
| cmd_gethbdelay}, |
| {"getinitparam", "getinitparam - get the default INIT parameters", |
| cmd_getinitparam}, |
| {"getinittsn", "getinittsn - get the association initial TSN", |
| cmd_getinittsn}, |
| {"getlocaladdrs", "getlocaladdrs [id] - get the local addresses for this assoc/ep", |
| cmd_getlocaladdrs}, |
| {"getloopsleep", "getloopsleep - Displays the sleep time between each loopreq before the send of loop-resp", |
| cmd_getloopsleep}, |
| |
| {"getmaxburst", "getmaxburst - retrieve the maxburst setting", |
| cmd_getmaxburst}, |
| {"getmaxseg", "getmaxseg - retrieve the maxseg size", |
| cmd_getmaxseg}, |
| {"getmsdelay", "getmsdelay - get the delayed send mode", |
| cmd_getmsdelay}, |
| {"getnodelay", "getnodelay - get the setting of the nagle algorithm off or on", |
| cmd_getnodelay}, |
| {"getstat", "getstat - retrieve the stat", |
| cmd_getstat}, |
| {"getassocstat", "getassocstat - retrieve the status of all associations", |
| cmd_getassocstat}, |
| {"clrstat", "clrstat - clear the stat", |
| cmd_clrstat}, |
| {"getpcbinfo", "getpcbinfo- retrieve the pcb counts", |
| cmd_getpcbinfo}, |
| {"getprimary", "getprimary - tells which net number is primary", |
| cmd_getprimary}, |
| {"getroute", "getroute [4|6|N] address - getaroute", |
| cmd_getroute}, |
| {"getrtt", "getrtt - Return the RTO of the current default address of the assoc", |
| cmd_getrtt}, |
| {"getrtomin", "getrtomin - Return the RTO MIN/MAX for the endpoint", |
| cmd_getrtomin}, |
| {"getsnd", "getsnd <asocid> - get the socketbuffer info for a asoc", |
| cmd_getsnd}, |
| {"gettimetolive", "gettimetolive - get the number of microseconds messages live", |
| cmd_gettimetolive}, |
| {"getv4mapped", "getv4mapped - get the v4-mapped addresses setting", |
| cmd_getv4mapped}, |
| |
| {"help", "help [cmd] - display help for cmd, or for all the commands if no cmd specified", |
| cmd_help}, |
| {"hulkstart", "hulkstart filename - start the hulk hogan process", |
| cmd_hulkstart}, |
| {"hulkstop", "hulkstop - stop the hulk hogan process", |
| cmd_hulkstop}, |
| {"initmultping", "initmultping - init contexts for a fast test", |
| cmd_initmultping}, |
| {"inqueue", "inqueue - report inqueue counts", |
| cmd_inqueue}, |
| {"listen", "listen backlog - executes a listen", |
| cmd_listen}, |
| {"multping", "multping size stream count blockafter sec - add a ping pong context and block\n" |
| "after <blockafter> instances for <sec> seconds", |
| cmd_multping}, |
| {"netstats", "netstats [optional:assoc_id]- return all network stats", |
| cmd_netstats}, |
| #ifndef SCTP_NO_TCP_MODEL |
| {"peeloff", "peeloff - peel off the current to assoc", |
| cmd_peeloff}, |
| #endif /* !SCTP_NO_TCP_MODEL */ |
| {"ping", "ping size stream count - play ping pong", |
| cmd_ping}, |
| {"quit", "quit - quit the program", |
| cmd_quit}, |
| {"rftp", "rftp filename strm1 strm2 blocksz [n] - round-trip ftp", |
| cmd_rftp}, |
| |
| {"rftp_stat", "rftp_stat - get stream status on read side of rftp and clear", |
| cmd_printrftpstat}, |
| {"rwnd", "rwnd - get rwnds", |
| cmd_rwnd}, |
| {"restorefd", "restorefd - restores the fd to the base for the TCP model", |
| cmd_restorefd}, |
| {"savepacketlog", "savepacketlog filename - pull a packet log and dump it to a file", |
| cmd_savepacketlog}, |
| {"send", "send string [n] - send string to a peer if a peer is set [and retrans n times]", |
| cmd_send}, |
| {"sendasoc", "sendasoc asocid string [n] - send string to a peer if a peer is set [and retrans n times]", |
| cmd_sendasoc}, |
| {"sendx", "sendx string port addr [addr addr] - send string to a peer with the listed addresses", |
| cmd_sctpsendx}, |
| {"sendloop", "sendloop [num] - send test script loopback request of num size", |
| cmd_sendloop}, |
| {"sendloopend", "sendloopend [num] - send test script loopback request of num size and terminate", |
| cmd_sendloopend}, |
| {"sendreltlv", "sendreltlv num - send a rel-tlv of num bytes of data", |
| cmd_sendreltlv}, |
| {"setadaption", "setadaption bits - include a adaption tlv sending these bits", |
| cmd_setadaption}, |
| {"setblocking", "setblocking on/off - turn on/off FIONBIO", |
| cmd_setblocking}, |
| |
| |
| {"getadaption", "getadaption - get the adaption bits sent", |
| cmd_getadaption}, |
| {"setfragmentation", "setfragmentation on/off - turn on/off fragmentation", |
| cmd_setfragmentation}, |
| {"getfragmentation", "getfragmentation - get fragmentation state", |
| cmd_getfragmentation}, |
| {"setautoclose", "setautoclose value - turn on/off autoclose time", |
| cmd_setautoclose}, |
| {"setbulkmode", "setbulkmode ascii/binary - set bulk transfer mode", |
| cmd_setbulkmode}, |
| {"setdefcookielife", "setdefcookielife num - set default cookie life", |
| cmd_setdefcookielife}, |
| {"setdefstream", "setdefstream num - set the default stream to", |
| cmd_setdefstream}, |
| {"seterr", "seterr num - set the association send error thresh", |
| cmd_seterr}, |
| {"setfd", "setfd num - set the fd to num (tcp model only)", |
| cmd_setfd}, |
| {"sethost", "sethost host|X.Y.Z.A - set the destination host IP address", |
| cmd_sethost}, |
| {"sethost6", "sethost6 host|xx:xx:xx...:xx - set the destination host IPv6 address", |
| cmd_sethost6}, |
| {"setinitparam", "setinitparam OS MIS maxinit initrtomax - set the association initial parameters", |
| cmd_setinitparam}, |
| |
| {"setinittsn", "setinittsn TSN - set the association initial TSN for debugging", |
| cmd_setinittsn}, |
| |
| {"setloopsleep", "setloopsleep val - Sets the sleep time between each loopreq before the send of loop-resp", |
| cmd_setloopsleep}, |
| |
| |
| {"setpdapi", "setpdapi value - set the partual delivery point", |
| cmd_setpdapi}, |
| |
| {"seteeor", "seteeor value - set the explict EOR mode on/off", |
| cmd_seteeor}, |
| |
| |
| {"setmaxburst", "setmaxburst val - set the maxburst setting to val", |
| cmd_setmaxburst}, |
| |
| {"setmaxseg", "setmaxseg val - set the maxseg size", |
| cmd_setmaxseg}, |
| |
| {"setneterr", "setneterr net val - set the association network error thresh", |
| cmd_setneterr}, |
| |
| {"setmsdelay", "setmsdelay 0/1 - set the delayed send mode 0=off/1=on", |
| cmd_setmsdelay}, |
| |
| {"setnodelay", "setnodelay 0/1 - set no delay 1=on 0=off (nagle on = 0 nagle off = 1)", |
| cmd_setnodelay}, |
| |
| {"settos", "settos val - set the v4 tos value with IPPROTO_IP/IP_TOS", |
| cmd_settos}, |
| |
| |
| {"setv4mapped", "setv4mapped 0/1 - set the v4-mapped addresses 0=off/1=on", |
| cmd_setv4mapped}, |
| |
| {"silentcnt", "silentcnt - get current rcv count in silent mode", |
| cmd_silentcnt}, |
| |
| {"silent", "silent - toggle silent running mode - toggle print on/off", |
| cmd_silent}, |
| |
| {"setautoasconf", "setautoasconf 0/1 - turn on/off auto asconf", |
| cmd_setautoasconf}, |
| |
| {"setdebug", "setdebug val - set sctp kernel debug level [off/all.. etc]", |
| cmd_setdebug}, |
| |
| {"setheartdelay", "setheartdelay time [ep]- Add number of seconds + RTO to hb interval", |
| cmd_heartdelay}, |
| |
| {"setopts", "setopts val - set options send options to value", |
| cmd_setopts}, |
| {"setpay", "setpay payloadt - set the payload type", |
| cmd_setpay}, |
| {"setport", "setport port - set the destination SCTP port number", |
| cmd_setport}, |
| {"setprimary", "setprimary - set current ip address to the primary address", |
| cmd_setprimary}, |
| {"setremprimary", "setremprimary address - set remote's primary address", |
| cmd_setremprimary}, |
| {"setrtomin", "setrtomin rtoinitial rtomin rtomax - Sets rto initial/min/max for the endpoint", |
| cmd_setrtomin}, |
| {"setscope", "setscope num - Set the IPv6 scope id", |
| cmd_setscope}, |
| {"setstreams", "setstreams numpreopenstrms - set the number of streams I request", |
| cmd_setstreams}, |
| {"settimetolive", "settimetolive mstolive - set the number of microseconds messages live", |
| cmd_settimetolive}, |
| |
| {"startmultping", "startmultping - start the defined ping pong contexts ", |
| cmd_startmultping}, |
| |
| {"streamreset", "streamreset [send|recv|both|tsn] [all || num num num] - reset streams ", |
| cmd_streamreset}, |
| |
| {"send_qdump", "send_qdump - Dump all send/t Q's ", |
| cmd_sendsent }, |
| {"deliverydump", "deliverydump - Dump all delivery Q stats ", |
| cmd_deliverydump}, |
| |
| {"tella", "tella host - confess what translateIPAddress returns", |
| cmd_tella}, |
| {"term", "term - terminate the set destination association (graceful shutdown)", |
| cmd_term}, |
| {"whereto", "whereto - tell where the default sends", |
| cmd_whereto}, |
| |
| {"addauth", "addauth - add a chunk(s) as requiring auth", |
| cmd_addauth}, |
| {"addkey", "addkey - set a shared key", |
| cmd_addkey}, |
| {"addnullkey", "addkey - set a shared null key", |
| cmd_addnullkey}, |
| {"deactivatekey", "deactivatekey - deactivate a shared key", |
| cmd_deactivatekey}, |
| {"deletekey", "deletekey - delete a shared key", |
| cmd_deletekey}, |
| {"setactivekey", "setactivekey - set a shared key as active", |
| cmd_setactivekey}, |
| {"getactivekey", "getactivekey - get the current active shared key", |
| cmd_getactivekey}, |
| {"sethmac", "sethmac - set the local hmac list for auth", |
| cmd_sethmac}, |
| {"gethmac", "gethmac - get the local hmac list for auth", |
| cmd_gethmac}, |
| {"getlocalauth", "getlocalauth - get the local chunks requiring auth", |
| cmd_getlocalauth}, |
| {"getpeerauth", "getpeerauth - get the peer chunks requiring auth", |
| cmd_getpeerauth}, |
| |
| {NULL, NULL, NULL} |
| }; |
| static sctpAdaptorMod *adap; |
| |
| int payload=0; |
| int pingPongCount=0; |
| char pingBuffer[SCTP_MAX_READBUFFER]; |
| int pingBufSize=0; |
| int pingStream=0; |
| int defStream = 0; |
| |
| distributor *dist; |
| |
| /* SCTP_PB */ |
| static SPingPongContext pingPongTable[MAX_PING_PONG_CONTEXTS]; |
| int pingPongsDefined=0; |
| |
| int bulkCount=0; |
| int bulkBufSize=0; |
| int bulkStream=0; |
| int bulkSeen=0; |
| int time_to_live=0; |
| |
| struct sctpdataToProduce{ |
| char string[8]; |
| struct timeval sent; |
| struct timeval recvd; |
| struct timeval stored; |
| uint32_t seq; |
| }; |
| |
| static uint32_t curSeq=0; |
| static int period = 20000; |
| FILE *hulkfile=NULL; |
| |
| FILE *rftp_in1=NULL, *rftp_in2=NULL; |
| FILE *rftp_out1=NULL, *rftp_out2=NULL; |
| int rftp_strm1, rftp_strm2, rftp_bsz, rftp_rt; |
| int rftp_ending1, rftp_ending2; |
| |
| /* how many message to read out at one time, max */ |
| #define LIMIT_READ_AT_ONCE 200 |
| |
| extern int mainnotDone; |
| extern int destinationSet; |
| extern int portSet; |
| extern int sendOptions; |
| extern int bulkInProgress; |
| extern int bulkPingMode; |
| extern int bindSpecific; |
| extern int scope_id; |
| |
| /* wire test structures */ |
| typedef struct { |
| u_char type; |
| u_char padding; |
| u_short dgramLen; |
| u_long dgramID; |
| }testDgram_t; |
| |
| #define SCTP_TEST_LOOPREQ 1 |
| #define SCTP_TEST_LOOPRESP 2 |
| #define SCTP_TEST_SIMPLE 3 |
| #define SCTP_TEST_RFTP 4 |
| #define SCTP_TEST_RFTPRESP 5 |
| |
| #if defined(__BSD_SCTP_STACK__) |
| char *namelist[]={ |
| "SCTP_PEG_SACKS_SEEN", |
| "SCTP_PEG_SACKS_SENT", |
| "SCTP_PEG_TSNS_SENT", |
| "SCTP_PEG_TSNS_RCVD", |
| "SCTP_DATAGRAMS_SENT", |
| "SCTP_DATAGRAMS_RCVD", |
| "SCTP_RETRANTSN_SENT", |
| "SCTP_DUPTSN_RECVD", |
| "SCTP_HBR_RECV", |
| "SCTP_HBA_RECV", |
| "SCTP_HB_SENT", |
| "SCTP_DATA_DG_SENT", |
| "SCTP_DATA_DG_RECV", |
| "SCTP_TMIT_TIMER", |
| "SCTP_RECV_TIMER", |
| "SCTP_HB_TIMER", |
| "SCTP_FAST_RETRAN", |
| "SCTP_TSNS_READ", |
| "SCTP_NONE_LEFT_TOSEND", |
| "SCTP_NONE_LEFT_RWND_GATE", |
| "SCTP_NONE_LEFT_CWND_GATE", |
| "SCTP_SEND_STREAM_0", |
| "SCTP_SEND_STREAM_1", |
| "SCTP_SEND_STREAM_2", |
| "SCTP_SEND_STREAM_3", |
| "SCTP_SEND_STREAM_OTHER", |
| "SCTP_RECV_STREAM_0", |
| "SCTP_RECV_STREAM_1", |
| "SCTP_RECV_STREAM_2", |
| "SCTP_RECV_STREAM_3", |
| "SCTP_RECV_STREAM_OTHER", |
| "UNKNOWN" |
| }; |
| #endif |
| |
| static sctp_assoc_t |
| get_assoc_id() |
| { |
| struct sctp_paddrinfo sp; |
| socklen_t siz; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| |
| /* First get the assoc id */ |
| siz = sizeof(sp); |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| memcpy((caddr_t)&sp.spinfo_address, sa, sa_len); |
| errno = 0; |
| if(getsockopt(adap->fd, IPPROTO_SCTP, SCTP_GET_PEER_ADDR_INFO, |
| &sp, &siz) != 0) { |
| printf("Failed to get assoc_id with GET_PEER_ADDR_INFO, errno:%d\n",errno); |
| return (0); |
| } |
| /* BSD: We depend on the fact that 0 can never be returned */ |
| return (sp.spinfo_assoc_id); |
| } |
| |
| void |
| SCTPPrintAnAddress(struct sockaddr *a) |
| { |
| char stringToPrint[256]; |
| u_short prt; |
| char *srcaddr,*txt; |
| if (a == NULL) { |
| printf("NULL\n"); |
| return; |
| } |
| if(a->sa_family == AF_INET){ |
| srcaddr = (char *)&((struct sockaddr_in *)a)->sin_addr; |
| txt = "IPv4 Address: "; |
| prt = ntohs(((struct sockaddr_in *)a)->sin_port); |
| }else if(a->sa_family == AF_INET6){ |
| srcaddr = (char *)&((struct sockaddr_in6 *)a)->sin6_addr; |
| prt = ntohs(((struct sockaddr_in6 *)a)->sin6_port); |
| txt = "IPv6 Address: "; |
| } |
| #ifndef linux |
| else if(a->sa_family == AF_LINK){ |
| int i; |
| char tbuf[200]; |
| u_char adbuf[200]; |
| struct sockaddr_dl *dl; |
| |
| dl = (struct sockaddr_dl *)a; |
| strncpy(tbuf,dl->sdl_data,dl->sdl_nlen); |
| tbuf[dl->sdl_nlen] = 0; |
| printf("Intf:%s (len:%d)Interface index:%d type:0x%x(%d) ll-len:%d ", |
| tbuf, |
| dl->sdl_nlen, |
| dl->sdl_index, |
| dl->sdl_type, |
| dl->sdl_type, |
| dl->sdl_alen |
| ); |
| memcpy(adbuf,LLADDR(dl),dl->sdl_alen); |
| for(i=0;i<dl->sdl_alen;i++){ |
| printf("%2.2x",adbuf[i]); |
| if(i<(dl->sdl_alen-1)) |
| printf(":"); |
| } |
| printf("\n"); |
| /* u_short sdl_route[16];*/ /* source routing information */ |
| return; |
| } |
| #endif |
| else{ |
| return; |
| } |
| if(inet_ntop(a->sa_family,srcaddr,stringToPrint,sizeof(stringToPrint))){ |
| if(a->sa_family == AF_INET6){ |
| printf("%s%s:%d scope:%d\n", |
| txt,stringToPrint,prt, |
| ((struct sockaddr_in6 *)a)->sin6_scope_id); |
| }else{ |
| printf("%s%s:%d\n",txt,stringToPrint,prt); |
| } |
| |
| }else{ |
| printf("%s unprintable?\n",txt); |
| } |
| } |
| |
| |
| int |
| sctpSEND(int fd, int defStream, char *s_buff, int sndsz, struct sockaddr *to, |
| int options, int payload, int not_used) |
| { |
| int sz; |
| errno = 0; |
| socklen_t to_len = 0; |
| |
| #if HAVE_SA_LEN |
| to_len = to->sa_len; |
| #else |
| if (to->sa_family == AF_INET) |
| to_len = sizeof(struct sockaddr_in); |
| else if (to->sa_family == AF_INET6) |
| to_len = sizeof(struct sockaddr_in6); |
| #endif |
| sz = sctp_sendmsg(fd, s_buff, sndsz, to, to_len, payload, options, |
| defStream, time_to_live, 0); |
| if((sz <=0) && (errno != ENOBUFS)){ |
| if(errno != EAGAIN) |
| printf("Return from sctp_sendmsg is %d errno %d\n", |
| sz,errno); |
| } |
| return(sz); |
| } |
| |
| int |
| sctpsend_associd (int fd, sctp_assoc_t asoc, char *s_buff, int sz, int options, |
| int payload) |
| { |
| int ret; |
| struct sctp_sndrcvinfo s_info; |
| errno = 0; |
| s_info.sinfo_stream = defStream; |
| s_info.sinfo_flags = options; |
| s_info.sinfo_ppid = payload; |
| s_info.sinfo_context = 0; |
| s_info.sinfo_timetolive = time_to_live; |
| s_info.sinfo_assoc_id = asoc; |
| |
| ret = sctp_send (fd, s_buff, sz, &s_info,0); |
| if((sz <=0) && (errno != ENOBUFS)){ |
| printf("Return from sctp_send is %d errno %d\n", |
| sz,errno); |
| } |
| return(ret); |
| } |
| |
| int |
| sctpTERMINATE(int fd, struct sockaddr *to) |
| { |
| char buf[16]; |
| return(sctpSEND(fd,0,buf,0,to,SCTP_EOF,0,0)); |
| } |
| |
| |
| /*--------------------------------------------------*/ |
| |
| void resetPingPongTable() |
| { |
| int i; |
| for(i=0;i<MAX_PING_PONG_CONTEXTS;i++){ |
| pingPongTable[i].stream = -1; |
| pingPongTable[i].nbRequests = 0; |
| pingPongTable[i].counter = 0; |
| pingPongTable[i].started = 0; |
| pingPongTable[i].blockAfter = 0; |
| pingPongTable[i].blockDuring = 0; |
| pingPongTable[i].blockTime = 0; |
| } |
| pingPongsDefined = 0; |
| return; |
| } |
| |
| /*--------------------------------------------------*/ |
| |
| void initPingPongTable(int max) |
| { |
| int i; |
| |
| for(i=0;i<max;i++){ |
| pingPongTable[i].stream = i; |
| pingPongTable[i].nbRequests = 2000; |
| pingPongTable[i].counter = 0; |
| pingPongTable[i].started = 0; |
| if(i == 2){ |
| pingPongTable[i].blockAfter = 100; |
| pingPongTable[i].blockDuring = 3; |
| }else{ |
| pingPongTable[i].blockAfter = 0; |
| pingPongTable[i].blockDuring = 0; |
| } |
| pingPongsDefined++; |
| } |
| return; |
| } |
| |
| |
| u_long translateIPAddress(char *host) |
| { |
| |
| struct sockaddr_in sa; |
| struct hostent *hp; |
| int len,cnt,i; |
| |
| sa.sin_addr.s_addr = htonl(inet_network(host)); |
| len = strlen(host); |
| cnt = 0; |
| for(i=0;i<len;i++){ |
| if(host[i] == '.') |
| cnt++; |
| else if(host[i] == ':') |
| cnt++; |
| } |
| if(cnt < 3){ |
| /* make it fail since it can't be a . or : based address */ |
| sa.sin_addr.s_addr = 0xffffffff; |
| } |
| if(sa.sin_addr.s_addr == 0xffffffff){ |
| hp = gethostbyname(host); |
| if(hp == NULL){ |
| return(htonl(strtoul(host,NULL,0))); |
| } |
| memcpy(&sa.sin_addr,hp->h_addr_list[0],sizeof(sa.sin_addr)); |
| } |
| return(sa.sin_addr.s_addr); |
| } |
| |
| void |
| fillPingBuffer(int fd,int len) |
| { |
| uint32_t *pbp; |
| int i,rlen; |
| rlen = (len/4) + 1; |
| pbp = (uint32_t *)&pingBuffer[4]; |
| for(i=0;i<rlen;i++){ |
| *pbp = (uint32_t)mrand48(); |
| pbp++; |
| } |
| } |
| |
| int |
| sendBulkTransfer(int fd,int sz) |
| { |
| char buffer[10000]; |
| testDgram_t *tt; |
| static unsigned int dgramCount=0; |
| int sndsz,ret; |
| |
| if((sz+sizeof(testDgram_t)) > (sizeof(buffer))){ |
| sndsz = sizeof(buffer) - sizeof(testDgram_t); |
| }else{ |
| sndsz = sz + sizeof(sizeof(testDgram_t)); |
| } |
| memset(buffer,0,sndsz); |
| tt = (testDgram_t *)buffer; |
| tt->type = SCTP_TEST_SIMPLE; |
| tt->dgramLen = sndsz - sizeof(testDgram_t); |
| tt->dgramID = dgramCount++; |
| |
| ret = sctpSEND(fd,defStream,buffer,sndsz,SCTP_getAddr(NULL),sendOptions,payload,0); |
| return(ret); |
| } |
| |
| |
| void |
| checkBulkTranfer(void *v,void *xxx, int foo) |
| { |
| int fd; |
| int ret,cnt; |
| |
| cnt = 0; |
| ret = 0; |
| fd = *((int *)v); |
| while(bulkCount > 0){ |
| if(bulkPingMode == 0){ |
| fillPingBuffer(fd,(bulkBufSize-4)); |
| ret = sctpSEND(fd,bulkStream,pingBuffer,bulkBufSize,SCTP_getAddr(NULL),sendOptions,0,0); |
| }else{ |
| ret = sendBulkTransfer(fd,bulkBufSize); |
| } |
| if(ret < 0){ |
| if(errno == ECONNRESET) { |
| printf("Connection reset, should really give up\n"); |
| } |
| if(errno != EAGAIN) { |
| printf("Error was %d on send?\n", errno); |
| } |
| dist_TimerStart(dist,checkBulkTranfer,0, |
| 20000,v,xxx); |
| return; |
| } |
| cnt++; |
| bulkCount--; |
| } |
| /* ask for the time again */ |
| if(bulkPingMode == 0){ |
| strcpy(pingBuffer,"time"); |
| ret = sctpSEND(fd,bulkStream,pingBuffer,5,SCTP_getAddr(NULL),sendOptions,0,0); |
| if(ret < 0){ |
| printf("Could not get time in, will wait ret:%d\n",ret); |
| dist_TimerStart(dist,checkBulkTranfer,0, |
| 200000,v,xxx); |
| return; |
| } |
| } |
| bulkInProgress = 0; |
| if(block_mode) { |
| int on_off; |
| /* turn off non-blocking mode */ |
| on_off = 0; |
| if(ioctl(adap->fd,FIONBIO,&block_mode) != 0) { |
| printf("IOCTL FIONBIO fails error:%d!\n",errno); |
| } |
| } |
| printf("bulk message are now queued time q ret:%d\n",ret); |
| } |
| |
| |
| void |
| handleMultiplePongs(int fd, struct sockaddr *from, int theStream) |
| { |
| int i, blocked = 0; |
| time_t now; |
| |
| |
| for(i = 0;i < MAX_PING_PONG_CONTEXTS;i++){ |
| if(pingPongTable[i].stream == theStream){ |
| pingPongTable[i].counter++; |
| if(pingPongTable[i].counter >= pingPongTable[i].nbRequests){ |
| /* The party is finished */ |
| time_t x; |
| struct tm *timeptr; |
| pingPongsDefined--; |
| x = time(0); |
| timeptr = localtime(&x); |
| printf("%s",asctime(timeptr)); |
| printf("--> Stream %d: ping pong completed \n", theStream); |
| printf(">"); |
| fflush(stdout); |
| pingPongTable[i].stream = -1; |
| pingPongTable[i].nbRequests = 0; |
| pingPongTable[i].counter = 0; |
| pingPongTable[i].started = 0; |
| pingPongTable[i].blockAfter = 0; |
| pingPongTable[i].blockDuring = 0; |
| pingPongTable[i].blockTime = 0; |
| }else{ |
| if((pingPongTable[i].counter % 10) == 0){ |
| printf("--> Stream %d: sending ping %d \n",theStream,pingPongTable[i].counter); |
| printf(">"); |
| fflush(stdout); |
| } |
| if(pingPongTable[i].blockAfter == pingPongTable[i].counter){ |
| printf("--> Stream %d: blocked at ping pong %d for %d seconds \n", |
| theStream, pingPongTable[i].counter, pingPongTable[i].blockDuring); |
| printf(">"); |
| pingPongTable[i].blockTime = time(0); |
| fflush(stdout); |
| }else{ |
| sctpSEND(fd,theStream,pingBuffer,pingBufSize,from,sendOptions,0,0); |
| } |
| } |
| } |
| } |
| /* Restart all candidate blocked streams */ |
| for(i=0;i<MAX_PING_PONG_CONTEXTS;i++){ |
| if(pingPongTable[i].blockTime != 0){ |
| blocked++; |
| } |
| } |
| for(i=0;i<MAX_PING_PONG_CONTEXTS;i++){ |
| if(pingPongTable[i].blockTime != 0){ |
| /* blockTime set means that the context is blocked */ |
| now = time(0); |
| if(now >= (pingPongTable[i].blockTime + pingPongTable[i].blockDuring)){ |
| pingPongTable[i].counter++; |
| pingPongTable[i].blockTime = 0; |
| printf("--> Stream %d: unblocked after %d seconds \n", |
| pingPongTable[i].stream, pingPongTable[i].blockDuring); |
| printf(">"); |
| sctpSEND(fd,pingPongTable[i].stream,pingBuffer,pingBufSize,from,sendOptions,0,0); |
| blocked--; |
| } |
| if(pingPongsDefined <= blocked){ |
| /* Hum: the remaining ping pongs are all blocked: we must force their unblocking, else |
| they will never wake up */ |
| pingPongTable[i].counter++; |
| pingPongTable[i].blockTime = 0; |
| printf("--> Stream %d: unblocked since the remaining %d streams are all blocked \n", |
| pingPongTable[i].stream, blocked); |
| printf(">"); |
| sctpSEND(fd,pingPongTable[i].stream,pingBuffer,pingBufSize,from,sendOptions,0,0); |
| } |
| } |
| } |
| return; |
| } |
| |
| /*--------------------------------------------------*/ |
| |
| void |
| SCTPdataTimerTicks(void *o,void *b, int foo) |
| { |
| int ret; |
| int fd; |
| struct sctpdataToProduce dp; |
| |
| fd = *((int *)b); |
| memset(&dp,0,sizeof(dp)); |
| strcpy(dp.string,"hulk"); |
| dp.sent = dist->lastKnownTime; |
| dp.seq = curSeq; |
| curSeq++; |
| ret = sctpSEND(fd,defStream,(char *)&dp,sizeof(dp), |
| SCTP_getAddr(NULL), sendOptions,payload,0); |
| if(ret < 0){ |
| printf("Send failed? errno:%d\n",errno); |
| return; |
| } |
| /* Restart the timer */ |
| dist_TimerStart(dist, |
| SCTPdataTimerTicks, |
| 0,period,o,b); |
| } |
| |
| |
| |
| static int str1Flow=0; |
| static int str2Flow=0; |
| |
| void |
| sendRftpTransfer(void *v, void *xxx, int foo) |
| { |
| char cbuf[10000]; |
| int bsz, readsz, ret1, ret2, sndsz; |
| testDgram_t *data; |
| int limit; |
| int fd; |
| struct sockaddr *sa; |
| |
| fd = *((int *)v); |
| limit = 0; |
| |
| if(rftp_bsz > 10000-sizeof(testDgram_t)) |
| bsz = 10000-sizeof(testDgram_t); |
| else bsz = rftp_bsz; |
| |
| data = (testDgram_t *)cbuf; |
| data->type = SCTP_TEST_RFTP; |
| while(1) { |
| /* do first stream */ |
| if(rftp_ending1 == 0) { |
| readsz = fread((void *)(cbuf+sizeof(testDgram_t)), 1, bsz, rftp_in1); |
| if(readsz == 0) rftp_ending1 = 1; |
| } else { |
| readsz = 0; |
| if(++rftp_ending1 == 5) { |
| printf("read done for stream %d\n",rftp_strm1); |
| fclose(rftp_in1); |
| } |
| } |
| if(rftp_ending1 <= 5){ |
| int ttt; |
| data->dgramLen = readsz; |
| sndsz = readsz + sizeof(testDgram_t); |
| ttt = time_to_live; |
| time_to_live = rftp_rt; |
| ret1 = sctpSEND(fd,rftp_strm1,cbuf,sndsz,SCTP_getAddr(NULL),sendOptions,payload,0); |
| time_to_live = ttt; |
| if(ret1 < 0) { |
| str1Flow++; |
| if(readsz > 0) |
| fseek(rftp_in1, (-1 * (long)readsz), SEEK_CUR); /* rewind position */ |
| break; |
| } else { |
| limit++; |
| } |
| } |
| |
| /* do second stream */ |
| if(rftp_ending2 == 0) { |
| readsz = fread((void *)(cbuf+sizeof(testDgram_t)), 1, bsz, rftp_in2); |
| if(readsz == 0) rftp_ending2 = 1; |
| } else { |
| readsz = 0; |
| if(++rftp_ending2 == 5) { |
| printf("read done for stream %d\n", rftp_strm2); |
| fclose(rftp_in2); |
| } |
| } |
| if(rftp_ending2 <= 5){ |
| int ttt; |
| data->dgramLen = readsz; |
| sndsz = readsz + sizeof(testDgram_t); |
| ttt = time_to_live; |
| time_to_live = rftp_rt; |
| ret2 = sctpSEND(fd,rftp_strm2,cbuf,sndsz,sa,sendOptions,payload,0); |
| time_to_live = ttt; |
| if(ret2 < 0) { |
| str2Flow++; |
| if(readsz > 0) |
| fseek(rftp_in2, (-1 * (long)readsz), SEEK_CUR); /* rewind position */ |
| break; |
| } else { |
| limit++; |
| } |
| } |
| if(rftp_ending1 >= 5 && rftp_ending2 >= 5) { |
| printf("Transfer to send queues complete s1flow:%d s2flow:%d\n", |
| str1Flow,str2Flow); |
| return; |
| } |
| } |
| if(rftp_ending1 >= 5 && rftp_ending2 >= 5) { |
| printf("Transfer 2 send queues complete\n"); |
| return; |
| } |
| dist_TimerStart(dist,sendRftpTransfer,0,20000,v,xxx); |
| } |
| |
| void |
| handleRftpTransfer(int fd,messageEnvolope *msg) |
| { |
| int ret; |
| char *dat; |
| int wrtSz; |
| if((rftp_in2 == NULL) || (rftp_in1 == NULL)){ |
| /* not in a transfer */ |
| return; |
| } |
| dat = (char *)((u_long)msg->data + sizeof(testDgram_t)); |
| wrtSz = msg->siz - sizeof(testDgram_t); |
| |
| if(msg->streamNo == rftp_strm1) { |
| if(wrtSz > 0) { |
| ret = fwrite((void *)dat, 1, wrtSz, rftp_out1); |
| if(ret != wrtSz) { |
| printf("write to strm 1 file incomplete\n"); |
| } |
| } else { |
| if(rftp_out1) { |
| fclose(rftp_out1); |
| rftp_out1 = NULL; |
| printf("done rcv strm %d\n", rftp_strm1); |
| } |
| } |
| }else if(msg->streamNo == rftp_strm2) { |
| if(wrtSz > 0) { |
| ret = fwrite((void *)dat, 1, wrtSz, rftp_out2); |
| if(ret != wrtSz) { |
| printf("write to strm 2 file incomplete\n"); |
| } |
| } else { |
| if(rftp_out2) { |
| fclose(rftp_out2); |
| rftp_out2 = NULL; |
| printf("done rcv strm %d\n", rftp_strm2); |
| } |
| } |
| }else { |
| printf("RFTP bad stream num %d!\n",msg->streamNo); |
| } |
| } |
| |
| |
| int |
| sendLoopRequest(int fd,int sz) |
| { |
| char buffer[15000]; |
| testDgram_t *tt; |
| static unsigned int dgramCount=0; |
| int sndsz,ret; |
| |
| if((sz+sizeof(testDgram_t)) > (sizeof(buffer))){ |
| sndsz = sizeof(buffer) - sizeof(testDgram_t); |
| }else{ |
| sndsz = sz + sizeof(sizeof(testDgram_t)); |
| } |
| memset(buffer,0,sizeof(buffer)); |
| tt = (testDgram_t *)buffer; |
| tt->type = SCTP_TEST_LOOPREQ; |
| tt->dgramLen = sndsz - sizeof(testDgram_t); |
| tt->dgramID = dgramCount++; |
| ret = sctpSEND(fd,defStream,buffer,sndsz,SCTP_getAddr(NULL),sendOptions,payload,0); |
| return(ret); |
| } |
| |
| void |
| handlePong(int fd, struct sockaddr *from, int mode) |
| { |
| pingPongCount--; |
| if(pingPongCount <= 0){ |
| /* done */ |
| time_t x; |
| struct tm *timeptr; |
| x = time(0); |
| timeptr = localtime(&x); |
| printf("%s",asctime(timeptr)); |
| printf("--Ping pong completes\n"); |
| fflush(stdout); |
| return; |
| } |
| if(mode == 0){ |
| sctpSEND(fd,pingStream,pingBuffer,pingBufSize,from,sendOptions,0,0); |
| }else{ |
| sendLoopRequest(fd,pingBufSize); |
| } |
| } |
| |
| |
| void |
| doPingPong(int fd) |
| { |
| time_t x; |
| int i; |
| struct tm *timeptr; |
| |
| if(bulkPingMode == 0){ |
| /* use ascii bulk ping mode.*/ |
| strncpy(pingBuffer,"ping",4); |
| for(i=4;i<pingBufSize;i++){ |
| pingBuffer[i] = 'A' + (i%26); |
| } |
| sctpSEND(fd,pingStream,pingBuffer,pingBufSize,SCTP_getAddr(NULL),sendOptions,payload,0); |
| }else{ |
| /* use binary bulk ping mode */ |
| sendLoopRequest(fd,pingBufSize); |
| } |
| x = time(0); |
| timeptr = localtime(&x); |
| printf("%s",asctime(timeptr)); |
| } |
| |
| void |
| handleHulk(int fd, |
| struct sockaddr *to, |
| struct sctpdataToProduce *dp) |
| { |
| int ret; |
| strcpy(dp->string,"sulk"); |
| dp->recvd = dist->lastKnownTime; |
| ret = sctpSEND(fd,defStream,(char *)dp,sizeof(*dp), |
| to,sendOptions,payload,0); |
| if(ret < 0){ |
| printf("Could not reply to a hulk with a sulk! %d:%d\n", |
| ret,errno); |
| } |
| } |
| |
| static int str1read=0; |
| static int str2read=0; |
| static uint32_t simplecnt=0; |
| static int modpacket=0; |
| static int phase_at = 0; |
| static char phase_list[] = { |
| '|', |
| '/', |
| '-', |
| '\\', |
| '|', |
| '/', |
| '-', |
| '\\', |
| }; |
| |
| static int bulk_count_seen = 0; |
| |
| void |
| sctpInput(void *arg, messageEnvolope *msg) |
| { |
| /* receive some number of datagrams and act on them. */ |
| |
| int disped,i; |
| int fd; |
| testDgram_t *testptr; |
| disped = i = 0; |
| |
| SCTP_setcurrent((sctpAdaptorMod *)arg); |
| if(msg->type == PROTOCOL_Sctp){ |
| fd = *((int *)msg->sender); |
| }else{ |
| /* we don't deal with non-sctp data */ |
| return; |
| } |
| testptr = (testDgram_t *)msg->data; |
| if(testptr->type == SCTP_TEST_LOOPREQ){ |
| /* another ping/pong type */ |
| /* printf("TEST_LOOPREQ send %d bytes str:%d seq:%d\n", |
| msg->siz,msg->streamNo,msg->streamSeq);*/ |
| testptr->type = SCTP_TEST_LOOPRESP; |
| if(loop_sleep) { |
| sleep(loop_sleep); |
| printf(">>>%c\r",phase_list[phase_at]); |
| fflush(stdout); |
| phase_at++; |
| if(phase_at > 7) { |
| phase_at = 0; |
| } |
| } |
| if(msdelaymode) { |
| struct timespec to,top; |
| modpacket++; |
| if((modpacket % msdelaymode) == 0) { |
| /* pause 10 ms every third msdelaymode packets */ |
| modpacket = 0; |
| to.tv_sec = 0; |
| to.tv_nsec = 10000000; |
| top = to; |
| nanosleep(&to,&top); |
| } |
| } |
| sctpSEND(fd,msg->streamNo,msg->data,msg->siz,(struct sockaddr *)msg->from, |
| sendOptions, msg->protocolId, 0); |
| msg->data = NULL; |
| }else if(testptr->type == SCTP_TEST_LOOPRESP){ |
| printf("Got a loop response\n"); |
| handlePong(fd,(struct sockaddr *)msg->from,1); |
| msg->data = NULL; |
| }else if(testptr->type == SCTP_TEST_SIMPLE){ |
| printf("Got a simple\n"); |
| simplecnt++; |
| if((simplecnt % 1000) == 0){ |
| printf("Have received %d simple dg's\n",simplecnt); |
| } |
| msg->data = NULL; |
| }else if(testptr->type == SCTP_TEST_RFTP){ |
| /* send the data back */ |
| testptr->type = SCTP_TEST_RFTPRESP; |
| if(msg->streamNo == 1){ |
| str1read++; |
| }else{ |
| str2read++; |
| } |
| sctpSEND(fd,msg->streamNo,msg->data,msg->siz,(struct sockaddr *)msg->from, |
| sendOptions, msg->protocolId,0); |
| msg->data = NULL; |
| }else if(testptr->type == SCTP_TEST_RFTPRESP){ |
| handleRftpTransfer(fd, msg); |
| msg->data = NULL; |
| }else if(strncmp(msg->data,"ping",4) == 0){ |
| /* it is a ping-pong message, send it back after changing |
| * the first 4 bytes to pong |
| */ |
| strncpy(msg->data,"pong",4); |
| sctpSEND(fd,msg->streamNo,msg->data,msg->siz,(struct sockaddr *)msg->from, |
| sendOptions, |
| msg->protocolId,0); |
| msg->data = NULL; |
| }else if(strcmp(msg->data,"time") == 0){ |
| struct tm *timeptr; |
| time_started = time(0); |
| timeptr = localtime(&time_started); |
| printf("have seen %d packets at %s",bulk_count_seen, asctime(timeptr)); |
| bulk_count_seen = 0; |
| msg->data = NULL; |
| bulkSeen = 0; |
| }else if(strncmp(msg->data,"pong",4) == 0){ |
| if(pingPongsDefined > 0){ |
| handleMultiplePongs(fd,(struct sockaddr *)msg->from,msg->streamNo); |
| }else{ |
| handlePong(fd,(struct sockaddr *)msg->from,0); |
| } |
| }else if(strncmp(msg->data,"hulk",4) == 0){ |
| handleHulk(fd, (struct sockaddr *)msg->from, |
| (struct sctpdataToProduce *)msg->data); |
| msg->data = NULL; |
| }else if(strncmp(msg->data,"sulk",4) == 0){ |
| if(hulkfile != NULL){ |
| struct sctpdataToProduce *dp; |
| dp = (struct sctpdataToProduce *)msg->data; |
| dp->stored = dist->lastKnownTime; |
| fwrite(msg->data,sizeof(struct sctpdataToProduce),1,hulkfile); |
| } |
| msg->data = NULL; |
| }else if(strncmp(msg->data,"bulk",4) == 0){ |
| bulkSeen++; |
| bulk_count_seen++; |
| }else{ |
| if(silent_mode == 0){ |
| /* display a text message */ |
| if(isascii(((char *)msg->data)[0])){ |
| printf("From:"); |
| SCTPPrintAnAddress(msg->from); |
| if(msg->to) { |
| printf("To:"); |
| SCTPPrintAnAddress(msg->to); |
| } |
| ((char *)msg->data)[msg->siz] = 0; |
| printf("PPID:%d strm:%d seq:%d %d:'%.10s'\n", |
| msg->protocolId, |
| msg->streamNo, |
| msg->streamSeq, |
| msg->siz, |
| (char *)msg->data); |
| disped = 1; |
| msg->data = NULL; |
| }else{ |
| printf("From:"); |
| SCTPPrintAnAddress(msg->from); |
| if(msg->to) { |
| printf("To:"); |
| SCTPPrintAnAddress(msg->to); |
| } |
| printf("PPID:%d strm:%d seq:%d %d:\n", |
| msg->protocolId, |
| msg->streamNo, |
| msg->streamSeq, |
| msg->siz); |
| printArry((uint8_t *)msg->data, (msg->siz > 32) ? 32 : msg->siz); |
| msg->data = NULL; |
| disped = 1; |
| } |
| }else{ |
| silent_count++; |
| } |
| } |
| if(disped){ |
| printf(">"); |
| fflush(stdout); |
| } |
| } |
| |
| |
| /* |
| * Called with a complete line of input by the readline library. |
| */ |
| static void |
| handleStdin2(char *line) |
| { |
| if (line == NULL || *line == '\0') |
| return; |
| execute_line(line); |
| add_history(line); |
| free(line); |
| } |
| |
| |
| |
| /* Called by the distributor each time stdin is ready for reading. |
| */ |
| int |
| stdinInFdHandler(void *arg,int fd, int event) |
| { |
| |
| if(fd != 0){ |
| printf("fd handler called with fd=%d not 0\n",fd); |
| return(0); |
| } |
| |
| /* XXX [MM] as a quick and dirty hack, set the adaptor to the global "adap". |
| * The correct fix is modify rl_callback_read_char to accept more |
| * than one parameter. |
| */ |
| |
| adap = (sctpAdaptorMod *) arg; |
| |
| |
| /* Read the next character from the input. If that completes the line, |
| * then call what has been setup with rl_callback_handler_install. |
| */ |
| rl_callback_read_char(); |
| return(0); |
| } |
| |
| |
| /* Initialize user interface handling. |
| */ |
| void |
| initUserInterface(distributor *o,struct sctpAdaptorMod *s) |
| { |
| /* Init the readline library, callback mode. */ |
| |
| /* Override the default completion done by the library, because |
| * we want to complete commands, not filenames. |
| */ |
| #if defined(__APPLE__) |
| rl_completion_entry_function = (rl_compentry_func_t *) command_generator; |
| /* rl_completion_entry_function = (Function *)command_generator;*/ |
| #else |
| rl_completion_entry_function = (rl_compentry_func_t *) command_generator; |
| #endif |
| /* Call handleStdin2 when a complete line of input has been entered. */ |
| rl_callback_handler_install(">>>", handleStdin2); |
| |
| dist = o; |
| dist_addFd(o,0,stdinInFdHandler,POLLIN,(void *)s); |
| resetPingPongTable(); |
| /* now subscribe for messages */ |
| dist_msgSubscribe(s->o, |
| sctpInput, |
| DIST_SCTP_PROTO_ID_DEFAULT,DIST_STREAM_DEFAULT, |
| 10,(void *)s); |
| } |
| |
| |
| /* Clean up the terminal and readline state. |
| */ |
| void |
| destroyUserInterface(void) |
| { |
| /* _rl_clean_up_for_exit(); */ |
| rl_deprep_term_function(); |
| } |
| |
| |
| /* Look up NAME as the name of a command, and return a pointer to that |
| * command or NULL if not found. |
| */ |
| static struct command * |
| find_command(char *name) |
| { |
| int i; |
| if(name == 0) |
| return(NULL); |
| if(name[0] == 0) |
| return(NULL); |
| for (i = 0; commands[i].co_name != NULL; i++) |
| if (strcmp(name, commands[i].co_name) == 0) |
| return(&commands[i]); |
| |
| return NULL; |
| } |
| |
| |
| /* Execute a command line. |
| * |
| * The line syntax is "command arg1 arg2 ..." (whitespace is separator). |
| * Put the args in an argv[] and invoke the proper function. |
| * |
| * Preconditions: |
| * line is not empty |
| */ |
| |
| static int |
| execute_line(const char *line) |
| { |
| struct command *command; |
| char *argv[10]; /* more than enough */ |
| char *buf, *cmd; |
| int i, ret; |
| |
| if (*line == '\0') |
| return -1; |
| bzero(argv, sizeof(argv)); |
| if ( (buf = strdup(line)) == NULL) { |
| perror("strdup"); |
| return -1; |
| } |
| /* break buf into pieces and put them in argv[] */ |
| cmd = strtok(buf, " \t"); |
| for (i = 0; i < 10; i++) { |
| if ( (argv[i] = strtok(NULL, " \t")) == NULL) |
| break; |
| } |
| /* Since the line may have been generated by command completion |
| * or by the user, we cannot be sure that it is a valid command name. |
| */ |
| if ( (command = find_command(cmd)) == NULL) { |
| printf("%s: No such command.\n", cmd); |
| return -1; |
| } |
| ret = command->co_func(argv, i); |
| free(buf); |
| return ret; |
| } |
| |
| |
| /* Generator function for command completion, called by the readline library. |
| * It returns a list of commands which match "text", one entry per invocation. |
| * Each entry must be freed by the function which has been setup with |
| * rl_callback_handler_install. The end of the list is marked by returning |
| * NULL. When called for the first time with a new "text", "state" is set to |
| * zero to allow for initialization. |
| */ |
| static char * |
| command_generator(char *text, int state) |
| { |
| static int index, len; |
| char *name; |
| |
| /* If this is a new word to complete, initialize now. */ |
| if (state == 0) { |
| index = 0; |
| len = strlen(text); |
| } |
| /* Return the next name which partially matches from the command list. */ |
| while ( (name = commands[index].co_name) != NULL) { |
| index++; |
| if (strncmp(name, text, len) == 0) |
| return strdup(name); |
| } |
| return NULL; /* no names matched */ |
| } |
| |
| |
| /* addip address [how] - add ip address where how is the mask/action to pass. |
| * New version using getaddrinfo. |
| */ |
| int |
| cmd_gettimetolive(char *argv[], int argc) |
| { |
| printf("Time to live of u-sctp messages is %d microseconds\n", |
| time_to_live); |
| return 0; |
| } |
| |
| int cmd_getassocids(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| sctp_assoc_t *ids; |
| unsigned int i; |
| socklen_t sz; |
| uint32_t number_of_assocs; |
| |
| sz = (socklen_t)sizeof(uint32_t); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_GET_ASSOC_NUMBER, (void *)&number_of_assocs, &sz) != 0) { |
| printf("Could not get the number of associations. Error: %s\n", strerror(errno)); |
| return(-1); |
| } |
| printf("There are currently %u associations.\n", number_of_assocs); |
| |
| if (number_of_assocs > 0) { |
| ids = (sctp_assoc_t *)malloc(number_of_assocs * sizeof(sctp_assoc_t)); |
| if (ids == NULL) { |
| printf("Could not allocate memory.\n"); |
| return (-1); |
| } |
| |
| sz = (socklen_t)(number_of_assocs * sizeof(sctp_assoc_t)); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_GET_ASSOC_ID_LIST, (void *)ids, &sz) != 0) { |
| printf("Could not get the association identifiers. Error: %s\n", strerror(errno)); |
| free(ids); |
| return (-1); |
| } |
| |
| for (i = 0; i < sz / sizeof(sctp_assoc_t); i++) { |
| printf("id:0x%x ", (uint32_t)ids[i]); |
| if ((i + 1) % 16 == 0) { |
| printf("\n"); |
| } |
| } |
| if ((i + 1) % 16 != 0) |
| printf("\n"); |
| free(ids); |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| int |
| cmd_sendsent(char *argv[], int argc) |
| { |
| printf("command no longer supported\n"); |
| return 0; |
| } |
| |
| int |
| cmd_deliverydump(char *argv[], int argc) |
| { |
| printf("command no longer supported\n"); |
| return 0; |
| } |
| |
| |
| int |
| cmd_savepacketlog(char *argv[], int argc) |
| { |
| FILE *fileio; |
| uint8_t buf[(SCTP_PACKET_LOG_SIZE + 4)]; |
| socklen_t len; |
| int ret; |
| |
| if (argc == 0) { |
| printf("Missing argument, need a file name to write\n"); |
| return (0); |
| } |
| len = sizeof(buf); |
| fileio = fopen(argv[0], "w+"); |
| if (fileio == NULL) { |
| printf("Can't open file %s error:%d\n", argv[0], errno); |
| return (0); |
| } |
| ret = getsockopt(adap->fd, IPPROTO_SCTP, SCTP_GET_PACKET_LOG, &buf, &len); |
| if(ret < 0) { |
| fclose(fileio); |
| printf("Could not get packet log error:%d\n", errno); |
| return (0); |
| } |
| printf("Retrieved %d bytes from the packet log\n", len); |
| if ((ret = fwrite(buf, 1, len, fileio)) < len) { |
| printf("Only wrote %d bytes errno:%d\n", ret, errno); |
| } |
| fclose(fileio); |
| return (0); |
| } |
| |
| int |
| cmd_setloopsleep(char *argv[], int argc) |
| { |
| if(argc == 0){ |
| printf("Missing argument, can't set unknown value\n"); |
| return(0); |
| } |
| loop_sleep = strtol(argv[0],NULL,0); |
| printf("loop sleep now set to %d\n",loop_sleep); |
| return(0); |
| } |
| int |
| cmd_getloopsleep(char *argv[], int argc) |
| { |
| printf("Loop sleep is set to %d seconds\n",loop_sleep); |
| return(0); |
| } |
| |
| int |
| cmd_addstreams(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| char buffer[2048]; |
| struct sctp_stream_reset *strrst; |
| memset(buffer,0,sizeof(buffer)); |
| strrst = (struct sctp_stream_reset *)buffer; |
| if(argc < 1) { |
| printf("addstream num - where num is the number to add\n"); |
| return(0); |
| } |
| strrst->strrst_num_streams = strtol(argv[0], NULL, 0); |
| strrst->strrst_flags = SCTP_RESET_ADD_STREAMS; |
| strrst->strrst_assoc_id = get_assoc_id(); |
| if((setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_RESET_STREAMS, |
| strrst, sizeof(struct sctp_stream_reset)) |
| ) != 0){ |
| printf("Stream Reset fails %d\n",errno); |
| }else{ |
| printf("Stream reset succesful\n"); |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| |
| int |
| cmd_streamreset(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| char buffer[2048]; |
| struct sctp_stream_reset *strrst; |
| int flag=0; |
| memset(buffer,0,sizeof(buffer)); |
| strrst = (struct sctp_stream_reset *)buffer; |
| if(argc < 2) { |
| jump_out: |
| printf("Missing argument(s), 'both|send|recv|tsn' 'all|num num num'\n"); |
| printf("------arg 1-----------\n"); |
| printf("both - gets both the send and recv streams reset\n"); |
| printf("recv - gets your receiving stream reset\n"); |
| printf("send - gets your sending stream reset\n"); |
| printf("------arg 2(-n)-----------\n"); |
| printf(" all - gets you all streams\n"); |
| printf(" num num num - gets you the listed numbered streams\n"); |
| return(0); |
| } |
| if ((strcmp(argv[0], "recv") == 0) || |
| (strcmp(argv[0], "RECV") == 0)) { |
| strrst->strrst_flags = SCTP_RESET_LOCAL_RECV; |
| } else if ((strcmp(argv[0], "send") == 0) || |
| (strcmp(argv[0], "SEND") == 0)) { |
| strrst->strrst_flags = SCTP_RESET_LOCAL_SEND; |
| } else if ((strcmp(argv[0], "tsn") == 0) || |
| (strcmp(argv[0], "TSN") == 0)) { |
| flag = 1; |
| strrst->strrst_flags = SCTP_RESET_TSN; |
| } else if ((strcmp(argv[0], "both") == 0) || |
| (strcmp(argv[0], "BOTH") == 0)) { |
| strrst->strrst_flags = SCTP_RESET_BOTH; |
| } else { |
| printf("First argument invalid, must be both|recv|send\n"); |
| goto jump_out; |
| } |
| |
| if(flag || |
| (strcmp(argv[1], "all") == 0) || |
| (strcmp(argv[1], "ALL") == 0)) { |
| strrst->strrst_num_streams = 0; |
| } else { |
| int i; |
| strrst->strrst_num_streams = argc - 1; |
| for(i=1;i<argc;i++) { |
| strrst->strrst_list[(i-1)] = strtol(argv[i],NULL,0); |
| printf("reseting stream %d\n",strrst->strrst_list[i]); |
| } |
| } |
| strrst->strrst_assoc_id = get_assoc_id(); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_RESET_STREAMS, |
| strrst, (sizeof(*strrst)+(strrst->strrst_num_streams * sizeof(uint16_t)))) != 0){ |
| printf("Stream Reset fails %d\n",errno); |
| }else{ |
| printf("Stream reset succesful\n"); |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| int |
| cmd_setdebug(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| uint32_t num,newlevel; |
| size_t sz; |
| |
| sz = sizeof(uint32_t); |
| if(sysctlbyname("net.inet.sctp.debug", &num, &sz, NULL, 0) < 0) { |
| printf("Sorry, Kernel debug levels not supported error:%d\n",errno); |
| return(0); |
| } |
| if(argc == 0){ |
| printf("Current settings are 0x%x\n",num); |
| }else{ |
| newlevel = strtoul(argv[0],NULL,0); |
| if(newlevel == 0){ |
| if(strcmp(argv[0],"off") == 0){ |
| printf("Turning all debug off\n"); |
| num = 0; |
| }else if(strncmp(argv[0],"timer",5) == 0){ |
| if (argv[0][5] == '1'){ |
| printf("adding timer level 1\n"); |
| num |= SCTP_DEBUG_TIMER1; |
| }else if (argv[0][5] == '2'){ |
| printf("adding timer level 2\n"); |
| num |= SCTP_DEBUG_TIMER2; |
| }else if (argv[0][5] == '3'){ |
| printf("adding timer level 3\n"); |
| num |= SCTP_DEBUG_TIMER3; |
| }else if (argv[0][5] == '4'){ |
| printf("adding timer level 4\n"); |
| num |= SCTP_DEBUG_TIMER4; |
| }else{ |
| printf("adding all timer levels\n"); |
| num |= SCTP_DEBUG_TIMER1; |
| num |= SCTP_DEBUG_TIMER2; |
| num |= SCTP_DEBUG_TIMER3; |
| num |= SCTP_DEBUG_TIMER4; |
| } |
| }else if(strncmp(argv[0],"output",6) == 0){ |
| if (argv[0][6] == '1'){ |
| printf("adding output level 1\n"); |
| num |= SCTP_DEBUG_OUTPUT1; |
| }else if (argv[0][6] == '2'){ |
| printf("adding output level 2\n"); |
| num |= SCTP_DEBUG_OUTPUT2; |
| }else if (argv[0][6] == '3'){ |
| printf("adding output level 3\n"); |
| num |= SCTP_DEBUG_OUTPUT3; |
| }else if (argv[0][6] == '4'){ |
| printf("adding output level 4\n"); |
| num |= SCTP_DEBUG_OUTPUT4; |
| }else{ |
| printf("adding all output levels\n"); |
| num |= SCTP_DEBUG_OUTPUT1; |
| num |= SCTP_DEBUG_OUTPUT2; |
| num |= SCTP_DEBUG_OUTPUT3; |
| num |= SCTP_DEBUG_OUTPUT4; |
| } |
| }else if(strncmp(argv[0],"input",5) == 0){ |
| if (argv[0][5] == '1'){ |
| printf("adding input level 1\n"); |
| num |= SCTP_DEBUG_INPUT1; |
| }else if (argv[0][5] == '2'){ |
| printf("adding input level 2\n"); |
| num |= SCTP_DEBUG_INPUT2; |
| }else if (argv[0][5] == '3'){ |
| printf("adding input level 3\n"); |
| num |= SCTP_DEBUG_INPUT3; |
| }else if (argv[0][5] == '4'){ |
| printf("adding input level 4\n"); |
| num |= SCTP_DEBUG_INPUT4; |
| }else{ |
| printf("adding all input levels\n"); |
| num |= SCTP_DEBUG_INPUT1; |
| num |= SCTP_DEBUG_INPUT2; |
| num |= SCTP_DEBUG_INPUT3; |
| num |= SCTP_DEBUG_INPUT4; |
| } |
| }else if(strncmp(argv[0],"util",4) == 0){ |
| if (argv[0][4] == '1'){ |
| printf("Adding util level 1\n"); |
| num |= SCTP_DEBUG_UTIL1; |
| }else if (argv[0][4] == '2'){ |
| printf("Adding util level 2\n"); |
| num |= SCTP_DEBUG_UTIL2; |
| }else{ |
| printf("Adding all util levels\n"); |
| num |= SCTP_DEBUG_UTIL1; |
| num |= SCTP_DEBUG_UTIL2; |
| } |
| }else if(strncmp(argv[0],"asconf",6) == 0){ |
| if (argv[0][6] == '1'){ |
| printf("Adding asconf level 1\n"); |
| num |= SCTP_DEBUG_ASCONF1; |
| }else if (argv[0][6] == '2'){ |
| printf("Adding asconf level 2\n"); |
| num |= SCTP_DEBUG_ASCONF2; |
| }else{ |
| printf("Adding all asconf levels\n"); |
| num |= SCTP_DEBUG_ASCONF1; |
| num |= SCTP_DEBUG_ASCONF2; |
| } |
| }else if(strncmp(argv[0],"pcb",3) == 0){ |
| if (argv[0][3] == '1'){ |
| printf("adding pcb level 1\n"); |
| num |= SCTP_DEBUG_PCB1; |
| }else if (argv[0][3] == '2'){ |
| printf("adding pcb level 2\n"); |
| num |= SCTP_DEBUG_PCB2; |
| }else if (argv[0][3] == '3'){ |
| printf("adding pcb level 3\n"); |
| num |= SCTP_DEBUG_PCB3; |
| }else if (argv[0][3] == '4'){ |
| printf("adding pcb level 4\n"); |
| num |= SCTP_DEBUG_PCB4; |
| }else{ |
| printf("adding all pcb levels\n"); |
| num |= SCTP_DEBUG_PCB1; |
| num |= SCTP_DEBUG_PCB2; |
| num |= SCTP_DEBUG_PCB3; |
| num |= SCTP_DEBUG_PCB4; |
| } |
| }else if(strncmp(argv[0],"indata",6) == 0){ |
| if (argv[0][6] == '1'){ |
| printf("adding indata level 1\n"); |
| num |= SCTP_DEBUG_INDATA1; |
| }else if (argv[0][6] == '2'){ |
| printf("adding indata level 2\n"); |
| num |= SCTP_DEBUG_INDATA2; |
| }else if (argv[0][6] == '3'){ |
| printf("adding indata level 3\n"); |
| num |= SCTP_DEBUG_INDATA3; |
| }else if (argv[0][6] == '4'){ |
| printf("adding indata level 4\n"); |
| num |= SCTP_DEBUG_INDATA3; |
| }else{ |
| printf("adding all indata levels\n"); |
| num |= SCTP_DEBUG_INDATA1; |
| num |= SCTP_DEBUG_INDATA2; |
| num |= SCTP_DEBUG_INDATA3; |
| num |= SCTP_DEBUG_INDATA3; |
| } |
| }else if(strncmp(argv[0],"usrreq",6) == 0){ |
| if (argv[0][6] == '1'){ |
| printf("Adding usrreq level 1\n"); |
| num |= SCTP_DEBUG_USRREQ1; |
| }else if (argv[0][6] == '2'){ |
| printf("Adding usrreq level 2\n"); |
| num |= SCTP_DEBUG_USRREQ2; |
| }else{ |
| printf("Adding all usrreq levels\n"); |
| num |= SCTP_DEBUG_USRREQ1; |
| num |= SCTP_DEBUG_USRREQ2; |
| } |
| }else if(strncmp(argv[0],"peel",4) == 0){ |
| printf("Adding the sctp peeloff level\n"); |
| num |= SCTP_DEBUG_PEEL1; |
| }else if(strncmp(argv[0],"auth",4) == 0){ |
| if (argv[0][4] == '1'){ |
| printf("Adding auth level 1\n"); |
| num |= SCTP_DEBUG_AUTH1; |
| }else if (argv[0][4] == '2'){ |
| printf("Adding auth level 2\n"); |
| num |= SCTP_DEBUG_AUTH2; |
| }else{ |
| printf("Adding all auth levels\n"); |
| num |= SCTP_DEBUG_AUTH1; |
| num |= SCTP_DEBUG_AUTH2; |
| } |
| }else if(strncmp(argv[0],"all",3) == 0){ |
| printf("adding ALL debug levels\n"); |
| num = SCTP_DEBUG_ALL; |
| }else{ |
| printf("Argument unrecognzied use either 0xnumber or\n"); |
| printf(" [timer[x]] or [util[x]] or [input[x]] or [all] or\n"); |
| printf(" [off] or [peel] or usrreq[x] or indata[x] or output[x] or\n"); |
| printf(" [asconf[x]] or pcb[x] or auth[x]\n"); |
| printf("Where the [x] is a level number, leave it off and all\n"); |
| printf("levels of that type are enabled\n"); |
| return(0); |
| } |
| }else{ |
| num = newlevel; |
| printf("Setting to level 0x%x\n",num); |
| } |
| if(sysctlbyname("net.inet.sctp.debug", NULL, NULL, &num, sizeof(num)) < 0) { |
| printf("Set fails error %d\n",errno); |
| }else{ |
| printf("Set of new level suceeds\n"); |
| } |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| int |
| cmd_silentcnt(char *argv[], int argc) |
| { |
| if(silent_mode){ |
| printf("Current silent count is 0x%x\n",silent_count); |
| }else{ |
| printf("Not in silent mode, but the last silent count was 0x%x\n", |
| silent_count); |
| } |
| return 0; |
| } |
| |
| int |
| cmd_silent(char *argv[], int argc) |
| { |
| if(silent_mode){ |
| printf("Disabling silent running mode - inbound msg will display\n"); |
| silent_mode = 0; |
| }else{ |
| printf("Enabling silent running mode - inbound msg will NOT display\n"); |
| silent_mode = 1; |
| silent_count = 0; |
| } |
| return 0; |
| } |
| |
| |
| |
| int |
| cmd_settimetolive(char *argv[], int argc) |
| { |
| if (argc < 1) { |
| printf("settimetolive: expected 1 argument(time-in-microseconds)\n"); |
| return -1; |
| } |
| time_to_live = strtoul(argv[0],NULL,0); |
| return 0; |
| } |
| |
| |
| static int |
| cmd_addip(char *argv[], int argc) |
| { |
| /* int fd = adap->fd;*/ |
| /* char *address;*/ |
| /* struct addrinfo hints, *res;*/ |
| /* int how, ret;*/ |
| /* |
| if (argc < 1) { |
| printf("addip: expected at least 1 argument\n"); |
| return -1; |
| } |
| */ |
| /* address = argv[0];*/ |
| /* how = argv[1] != NULL ? strtol(argv[1], NULL, 0) : 0;*/ |
| |
| /* bzero(&hints, sizeof(hints));*/ |
| /* hints.ai_flags = AI_NUMERICHOST;*/ /* disable name resolution */ |
| /* ret = getaddrinfo(address, NULL, &hints, &res); |
| if (ret != 0) { |
| printf("addip: getaddrinfo: %s\n", gai_strerror(ret)); |
| return -1; |
| } |
| */ |
| /* printf("addip: adding IP address %s, action 0x%x\n", address, how);*/ |
| /* ret = sctpADDIPADDRESS(fd, res->ai_addr, SCTP_getAddr(), how);*/ |
| /* if (ret != 1) { |
| printf("addip: failed, return value: %d\n", ret); |
| } else { |
| printf("addip: success\n"); |
| } |
| freeaddrinfo(res); |
| */ |
| /* return ret != 1 ? -1 : 0;*/ |
| return 0; |
| } |
| |
| int |
| cmd_getrtomin(char *argv[], int argc) |
| { |
| struct sctp_rtoinfo optval; |
| socklen_t siz; |
| |
| siz = sizeof(optval); |
| memset(&optval,0,sizeof(optval)); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, SCTP_RTOINFO, &optval, &siz) != 0) { |
| printf("Can't get RTOINFO on socket err:%d!\n",errno); |
| }else{ |
| printf("RTO initial is %d ms\n",optval.srto_initial); |
| printf("RTO MAX is %d ms\n",optval.srto_max); |
| printf("RTO MIN is %d ms\n",optval.srto_min); |
| } |
| return(0); |
| } |
| int |
| cmd_setrtomin(char *argv[], int argc) |
| { |
| struct sctp_rtoinfo optval; |
| if (argc < 3) { |
| printf("setrtomin: expected 3 arguments (rtoinit rtomax rtomin)\n"); |
| return -1; |
| } |
| memset(&optval,0,sizeof(optval)); |
| |
| optval.srto_initial = (argv[0] != NULL) ? strtoul(argv[0], NULL, 0) : 0; |
| optval.srto_max = (argv[1] != NULL) ? strtoul(argv[1], NULL, 0) : 0; |
| optval.srto_min = (argv[2] != NULL) ? strtoul(argv[2], NULL, 0) : 0; |
| |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_RTOINFO, &optval, sizeof(optval)) != 0) { |
| printf("Can't get RTOINFO on socket err:%d!\n",errno); |
| }else{ |
| printf("set socket option succeeds new values are:\n"); |
| printf("RTO initial is now %d ms\n",optval.srto_initial); |
| printf("RTO MAX is now %d ms\n",optval.srto_max); |
| printf("RTO MIN is now %d ms\n",optval.srto_min); |
| |
| } |
| return(0); |
| } |
| |
| int cmd_getinitparam(char *argv[], int argc) |
| { |
| socklen_t siz; |
| struct sctp_initmsg optval; |
| |
| siz = sizeof(optval); |
| |
| memset(&optval,0,sizeof(optval)); |
| if(getsockopt(adap->fd, IPPROTO_SCTP, SCTP_INITMSG, &optval, &siz) != 0) { |
| printf("Can't get SCTP_INITMSG on socket err:%u!\n", errno); |
| }else{ |
| printf("OS we request is %d\n",optval.sinit_num_ostreams); |
| printf("MIS we limit is %d \n",optval.sinit_max_instreams); |
| printf("Max INIT attempts is %d\n",optval.sinit_max_attempts); |
| printf("Max INIT RTO is %d\n", optval.sinit_max_init_timeo); |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_getautoclose(char *argv[], int argc) |
| { |
| uint32_t adaption; |
| socklen_t sz; |
| |
| sz = sizeof(adaption); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_AUTOCLOSE, |
| &adaption, &sz) != 0) { |
| printf("Can't get autoclose setting socket err:%d!\n",errno); |
| }else{ |
| if(adaption){ |
| printf("Autoclose is on and set to %d\n",adaption); |
| }else{ |
| printf("Autoclose is off!\n"); |
| } |
| } |
| return(0); |
| |
| } |
| |
| static int cmd_getmsdelay(char *argv[], int argc) |
| { |
| if(msdelaymode) |
| printf("ms delay is ON\n"); |
| else |
| printf("ms delay is OFF\n"); |
| return(0); |
| } |
| |
| static int cmd_setmsdelay(char *argv[], int argc) |
| { |
| if(argc < 1) { |
| printf("Use setmsdelay val\n"); |
| return -1; |
| } |
| msdelaymode = strtol(argv[0],NULL,0); |
| if(msdelaymode) |
| printf("ms delay is now ON\n"); |
| else |
| printf("ms delay is now OFF\n"); |
| return(0); |
| } |
| |
| static int cmd_getnodelay(char *argv[], int argc) |
| { |
| uint32_t seg; |
| socklen_t sz; |
| |
| sz = sizeof(seg); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_NODELAY, |
| &seg, &sz) != 0) { |
| printf("Can't get nagle setting socket err:%d!\n",errno); |
| }else{ |
| if(seg) |
| printf("Nagle is OFF\n"); |
| else |
| printf("Nagle is ON\n"); |
| } |
| return(0); |
| } |
| |
| static int cmd_setnodelay(char *argv[], int argc) |
| { |
| uint32_t seg,sz; |
| |
| if(argc < 1) { |
| printf("Use setnodelay val\n"); |
| return -1; |
| } |
| seg = strtol(argv[0],NULL,0); |
| sz = sizeof(seg); |
| |
| printf("Setting max seg to %s\n",((seg) ? "OFF" : "ON")); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_NODELAY, |
| &seg, sz) != 0) { |
| printf("Can't set sctp_nodelay setting socket err:%d!\n",errno); |
| }else{ |
| printf("nagle is now %s\n",((seg) ? "OFF" : "ON")); |
| |
| } |
| return(0); |
| } |
| |
| static int cmd_getv4mapped(char *argv[], int argc) |
| { |
| uint32_t optval; |
| socklen_t optlen; |
| |
| optlen = sizeof(optval); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, |
| &optval, &optlen) != 0) { |
| printf("Can't get v4-mapped addresses, errno:%d!\n", errno); |
| } else { |
| printf("IPv4-mapped addresses is %s\n",((optval) ? "ON" : "OFF")); |
| } |
| return (0); |
| } |
| |
| |
| static int cmd_settos(char *argv[], int argc) |
| { |
| uint32_t optval; |
| socklen_t optlen; |
| int ret; |
| |
| if (argc < 1) { |
| printf("Use settos tos-value\n"); |
| return -1; |
| } |
| optval = strtoul(argv[0], NULL, 0); |
| optlen = sizeof(optval); |
| ret = setsockopt(adap->fd, IPPROTO_IP, IP_TOS, &optval, optlen); |
| if (ret < 0) { |
| printf("setsockopt fails errno:%d\n", errno); |
| } else { |
| printf("Success\n"); |
| } |
| return 0; |
| } |
| |
| static int cmd_setv4mapped(char *argv[], int argc) |
| { |
| uint32_t optval; |
| socklen_t optlen; |
| |
| if (argc < 1) { |
| printf("Use setv4mapped <on/off val>\n"); |
| return -1; |
| } |
| optval = strtol(argv[0], NULL, 0); |
| optlen = sizeof(optval); |
| |
| printf("Setting IPv4-mapped addresses to %s\n",((optval) ? "ON" : "OFF")); |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, |
| &optval, optlen) != 0) { |
| printf("Can't set v4-mapped addresses, errno:%d!\n",errno); |
| } else { |
| printf("IPv4-mapped addresses is now %s\n",((optval) ? "ON" : "OFF")); |
| } |
| return (0); |
| } |
| |
| static int cmd_getmaxseg(char *argv[], int argc) |
| { |
| struct sctp_assoc_value av; |
| socklen_t sz; |
| |
| |
| if(argc == 1) { |
| av.assoc_id = strtoul(argv[0], NULL, 0); |
| } else { |
| av.assoc_id = 0; |
| } |
| av.assoc_value = 0; |
| sz = sizeof(struct sctp_assoc_value); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_MAXSEG, |
| &av, &sz) != 0) { |
| printf("Can't get maxseg setting socket err:%d!\n",errno); |
| }else{ |
| if(av.assoc_id) { |
| printf("Maxseg for the assoc:%x is %d\n", |
| av.assoc_id, av.assoc_value); |
| } else { |
| printf("Maxseg for the endpoint is %d\n", |
| av.assoc_value); |
| } |
| } |
| return(0); |
| } |
| |
| static int cmd_setmaxseg(char *argv[], int argc) |
| { |
| struct sctp_assoc_value av; |
| socklen_t sz; |
| |
| if(argc < 1) { |
| printf("Use setmaxseg val\n"); |
| return -1; |
| } |
| av.assoc_id = 0; |
| av.assoc_value = strtol(argv[0],NULL,0); |
| sz = sizeof(struct sctp_assoc_value); |
| |
| printf("Setting max seg to %d\n", av.assoc_value); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_MAXSEG, |
| &av, sz) != 0) { |
| printf("Can't set maxseg setting socket err:%d!\n",errno); |
| }else{ |
| printf("Maxseg is %d\n", |
| av.assoc_value); |
| } |
| return(0); |
| |
| } |
| |
| |
| static int |
| cmd_getmaxburst(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| uint32_t burst; |
| socklen_t sz; |
| |
| sz = sizeof(burst); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_MAXBURST, |
| &burst, &sz) != 0) { |
| printf("Can't get maxburst setting socket err:%d!\n",errno); |
| }else{ |
| printf("Maxburst is %d\n", |
| burst); |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int |
| cmd_setmaxburst(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| uint32_t burst,sz; |
| |
| if(argc < 1) { |
| printf("Use setmaxburst val\n"); |
| return -1; |
| } |
| burst = strtol(argv[0],NULL,0); |
| sz = sizeof(burst); |
| |
| printf("Setting max burst to %d\n",burst); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_MAXBURST, |
| &burst, sz) != 0) { |
| printf("Can't set maxburst setting socket err:%d!\n",errno); |
| }else{ |
| printf("Maxburst is %d\n", |
| burst); |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int |
| cmd_setautoclose(char *argv[], int argc) |
| { |
| uint32_t adaption; |
| if (argc < 1) { |
| printf("setautoclose: expects an argument (0 turns it off)\n"); |
| return -1; |
| } |
| adaption = (argv[0] != NULL) ? strtoul(argv[0], NULL, 0) : 0; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_AUTOCLOSE, |
| &adaption, sizeof(adaption)) != 0) { |
| printf("Can't set autoclose value on socket err:%d!\n",errno); |
| } |
| return(0); |
| } |
| |
| |
| static int |
| cmd_getfragmentation(char *argv[], int argc) |
| { |
| uint32_t adaption; |
| socklen_t sz; |
| |
| sz = sizeof(adaption); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_DISABLE_FRAGMENTS, |
| &adaption, &sz) != 0) { |
| printf("Can't get fragmentation setting socket err:%d!\n",errno); |
| }else{ |
| printf("Adaption bits returned are 0x%x\n",adaption); |
| if(adaption == 1){ |
| printf("Fragmentation is NOT being performed by SCTP\n"); |
| }else{ |
| printf("Fragmentation is being performed by SCTP\n"); |
| } |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_setfragmentation(char *argv[], int argc) |
| { |
| uint32_t adaption; |
| if (argc < 1) { |
| printf("setfragment: expects an argument (0 turns it off)\n"); |
| return -1; |
| } |
| adaption = (argv[0] != NULL) ? strtoul(argv[0], NULL, 0) : 0; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_DISABLE_FRAGMENTS, |
| &adaption, sizeof(adaption)) != 0) { |
| printf("Can't set fragmentation flag on socket err:%d!\n",errno); |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_setblocking(char *argv[], int argc) |
| { |
| int on_off; |
| if (argc < 1) { |
| printf("setblocking: expects an argument (on/off)\n"); |
| return -1; |
| } |
| if(strcmp(argv[0],"blocking") == 0){ |
| block_mode = 1; |
| on_off = 0; |
| }else if(strcmp(argv[0],"non-blocking") == 0){ |
| block_mode = 0; |
| on_off = 1; |
| }else{ |
| printf("Argument '%s' incorrect on/off please\n",argv[0]); |
| return(-1); |
| } |
| if(ioctl(adap->fd,FIONBIO,&on_off) != 0) { |
| printf("IOCTL FIONBIO fails error:%d!\n",errno); |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_getblocking(char *argv[], int argc) |
| { |
| if(block_mode) |
| printf("I/O is blocking\n"); |
| else |
| printf("I/O is NON-blocking\n"); |
| return (0); |
| } |
| |
| |
| static int |
| cmd_setadaption(char *argv[], int argc) |
| { |
| uint32_t adaption; |
| if (argc < 1) { |
| printf("setadaption: expects an argument (0 turns it off)\n"); |
| return -1; |
| } |
| adaption = (argv[0] != NULL) ? strtoul(argv[0], NULL, 0) : 0; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ADAPTION_LAYER, |
| &adaption, sizeof(adaption)) != 0) { |
| printf("Can't set adaption bits on socket err:%d!\n",errno); |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_getadaption(char *argv[], int argc) |
| { |
| uint32_t adaption; |
| socklen_t sz; |
| |
| sz = sizeof(adaption); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ADAPTION_LAYER, |
| &adaption, &sz) != 0) { |
| printf("Can't get adaption bits on socket err:%d!\n",errno); |
| }else{ |
| printf("Adaption bits to be sent are %u\n",adaption); |
| } |
| return(0); |
| } |
| |
| |
| int cmd_setinittsn(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| uint32_t init_tsn; |
| if (argc < 1) { |
| printf("setinittsn: expects a TSN number as a argument (0 turns it off)\n"); |
| return -1; |
| } |
| init_tsn = (argv[0] != NULL) ? strtoul(argv[0], NULL, 0) : 0; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_SET_INITIAL_DBG_SEQ, &init_tsn, sizeof(init_tsn)) != 0) { |
| printf("Can't set initial tsn on socket err:%d!\n",errno); |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| int cmd_getinittsn(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| uint32_t init_tsn; |
| socklen_t sz; |
| |
| init_tsn = 0; |
| sz = sizeof(init_tsn); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_SET_INITIAL_DBG_SEQ, &init_tsn,&sz) != 0) { |
| printf("Can't get initial tsn on socket err:%d!\n",errno); |
| }else{ |
| if(init_tsn){ |
| printf("Initial TSN set to 0x%x\n",init_tsn); |
| }else{ |
| printf("Initial TSN will be a random number\n"); |
| } |
| } |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| |
| int cmd_setinitparam(char *argv[], int argc) |
| { |
| struct sctp_initmsg optval; |
| if (argc < 4) { |
| printf("setinitparam: expected 4 arguments (OS MIS maxinit initrtomax)\n"); |
| return -1; |
| } |
| optval.sinit_num_ostreams = (argv[0] != NULL) ? strtoul(argv[0], NULL, 0) : 0; |
| optval.sinit_max_instreams = (argv[1] != NULL) ? strtoul(argv[1], NULL, 0) : 0; |
| optval.sinit_max_attempts = (argv[2] != NULL) ? strtoul(argv[2], NULL, 0) : 0; |
| optval.sinit_max_init_timeo = (argv[3] != NULL) ? strtoul(argv[3], NULL, 0) : 0; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_INITMSG, &optval, sizeof(optval)) != 0) { |
| printf("Can't set SCTP_INITMSG on socket err:%d!\n",errno); |
| }else{ |
| printf("OS set to %d\n",optval.sinit_num_ostreams); |
| printf("MIS limited to %d \n",optval.sinit_max_instreams); |
| printf("Max INIT set to %d\n",optval.sinit_max_attempts); |
| printf("Max INIT RTO set to %d\n", optval.sinit_max_init_timeo); |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_abort(char *argv[], int argc) |
| { |
| char buf[4]; |
| |
| memset(buf, 0, sizeof(buf)); |
| return (sctpSEND(adap->fd, 0, buf, 0, SCTP_getAddr(NULL), SCTP_ABORT, |
| 0, 0)); |
| } |
| |
| static int |
| cmd_abortassoc(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int ret; |
| uint32_t aaa; |
| sctp_assoc_t asoc; |
| if (argc != 1) { |
| printf("abortasoc: expected 1 argument\n"); |
| return -1; |
| } |
| aaa = strtoul(argv[0], NULL, 0); |
| if(aaa == 0) { |
| printf("Sorry asocid 0 never valid\n"); |
| return -1; |
| } |
| asoc = (sctp_assoc_t)aaa; |
| ret = sctpsend_associd(fd, asoc, NULL, 0, SCTP_ABORT, 0); |
| printf("sctpsend_associd returned %d from the send\n",ret); |
| return 0; |
| } |
| |
| /* assoc - associate with the set destination |
| */ |
| static int |
| cmd_assoc(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int ret; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| |
| if (!(destinationSet && portSet)) { |
| printf("Please set the destination/port before\n"); |
| return -1; |
| } |
| if (fd == -1) { |
| printf("sorry m is NULL?\n"); |
| return -1; |
| } |
| sa = SCTP_getAddr(&sa_len); |
| ret = connect(fd, sa, sa_len); |
| printf("Connect returns %d errno:%d\n",ret,errno); |
| return 0; |
| } |
| |
| int |
| cmd_xconnect(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| int len,i,addrcnt=0,ret,llen; |
| char *ccc; |
| sctp_assoc_t id; |
| struct sockaddr *at; |
| struct sockaddr_in *servaddr; |
| struct sockaddr_in6 *servaddr6; |
| |
| if (!portSet) { |
| printf("Please set a port first\n"); |
| return -1; |
| } |
| if(argc == 0) { |
| printf("Use connectx ip-addr [ip-addr ip-addr]\n"); |
| return -1; |
| } |
| len = (sizeof(struct sockaddr_storage) * argc); |
| ccc = malloc(len); |
| if(ccc == NULL) { |
| printf("Sorry can't get memory %d\n",errno); |
| return 0; |
| } |
| memset(ccc,0,len); |
| at = (struct sockaddr *)ccc; |
| for(i=0;i<argc;i++){ |
| servaddr6 = (struct sockaddr_in6 *)at; |
| if(inet_pton(AF_INET6,argv[i], &servaddr6->sin6_addr)) { |
| servaddr6->sin6_family = AF_INET6; |
| llen = sizeof(struct sockaddr_in6); |
| #ifdef HAVE_SA_LEN |
| servaddr6->sin6_len = sizeof(struct sockaddr_in6); |
| #endif |
| servaddr6->sin6_port = SCTP_getport(); |
| } else { |
| servaddr = (struct sockaddr_in *)at; |
| if (inet_pton(AF_INET, argv[i], &servaddr->sin_addr) ){ |
| servaddr->sin_family = AF_INET; |
| llen = sizeof(struct sockaddr_in); |
| #ifdef HAVE_SA_LEN |
| servaddr->sin_len = sizeof(struct sockaddr_in); |
| #endif |
| servaddr->sin_port = SCTP_getport(); |
| } else { |
| printf("Skipping address %s, unknown type\n", |
| argv[i]); |
| continue; |
| } |
| } |
| addrcnt++; |
| at = (struct sockaddr *)((caddr_t)at + llen); |
| } |
| at = (struct sockaddr *)ccc; |
| servaddr = (struct sockaddr_in *)at; |
| if(servaddr->sin_family == AF_INET) { |
| SCTP_setIPaddr(servaddr->sin_addr.s_addr); |
| } else if (servaddr->sin_family == AF_INET6) { |
| servaddr6 = (struct sockaddr_in6 *)at; |
| SCTP_setIPaddr6((u_char *)&servaddr6->sin6_addr); |
| } |
| ret = sctp_connectx(adap->fd, at, addrcnt, &id); |
| if(ret) |
| printf("Connectx returns %d errno:%d\n",ret,errno); |
| free(ccc); |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int |
| cmd_bindx(char *argv[], int argc) |
| { |
| int bindType = 0; |
| int bindOption = 0; |
| char bindx_ss[sizeof(struct sockaddr_storage)]; |
| struct sockaddr_in6 *sin6; |
| struct sockaddr_in *sin; |
| socklen_t sa_len; |
| |
| if (argc < 2) { |
| printf("bindx: invalid number of arguments\n"); |
| return -1; |
| } |
| if (bindSpecific == 0) { |
| printf("Endpoint is BOUNDALL... ignoring\n"); |
| return -1; |
| } |
| /* get the bindx type */ |
| bindType = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if (bindType == 0) |
| bindOption = SCTP_BINDX_ADD_ADDR; |
| else if (bindType == 1) |
| bindOption = SCTP_BINDX_REM_ADDR; |
| else { |
| printf("bindx: invalid 'type'=%u\n", bindType); |
| return -1; |
| } |
| sin6 = (struct sockaddr_in6 *)bindx_ss; |
| sin = (struct sockaddr_in *)bindx_ss; |
| bzero(bindx_ss, sizeof(bindx_ss)); |
| if (inet_pton(AF_INET6, argv[1], &sin6->sin6_addr)) { |
| /* ipv6 address specified */ |
| sin6->sin6_family = AF_INET6; |
| #ifdef HAVE_SA_LEN |
| sin6->sin6_len = sizeof(struct sockaddr_in6); |
| #endif |
| sa_len = sizeof(struct sockaddr_in6); |
| sin6->sin6_scope_id = scope_id; |
| } else if (inet_pton(AF_INET, argv[1], &sin->sin_addr)) { |
| /* ipv4 address specified */ |
| sin->sin_family = AF_INET; |
| #ifdef HAVE_SA_LEN |
| sin->sin_len = sizeof(struct sockaddr_in); |
| #endif |
| sa_len = sizeof(struct sockaddr_in); |
| } else { |
| printf("bindx: invalid address\n"); |
| return -1; |
| } |
| /* do the bindx... */ |
| if (sctp_bindx(adap->fd, (struct sockaddr *)bindx_ss, 1, bindOption) == -1) { |
| printf("Failed bindx() on socket err:%u!\n", errno); |
| } else { |
| printf("bindx() completed\n"); |
| } |
| return 0; |
| } |
| |
| |
| /* bulk size stream count - send a bulk of messages |
| */ |
| static int |
| cmd_sendN(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int ret,i; |
| if (argc < 3) { |
| printf("bulk: expected 3 arguments\n"); |
| return -1; |
| } |
| bulkBufSize = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| bulkStream = argv[1] != NULL ? strtol(argv[1], NULL, 0) : 0; |
| bulkCount = argv[2] != NULL ? strtol(argv[2], NULL, 0) : 0; |
| if(bulkBufSize > SCTP_MAX_READBUFFER){ |
| printf("bulk: size %d is to large, overriding to largest I can" |
| "handle %d\n", bulkBufSize, SCTP_MAX_READBUFFER); |
| bulkBufSize = SCTP_MAX_READBUFFER; |
| }else if (bulkBufSize <= 0) { |
| printf("bulk: size must be positive\n"); |
| return -1; |
| } |
| /* prepare ping buffer */ |
| /* ask for the time */ |
| strncpy(pingBuffer,"bulk",4); |
| checkBulkTranfer((void *)&adap->fd,NULL, 0); |
| for (i=0; i<bulkCount; i++) { |
| ret = sctpSEND(fd,bulkStream,pingBuffer,bulkBufSize,SCTP_getAddr(NULL),sendOptions,payload,0); |
| if (ret < 0) { |
| printf("sending aborts ret:%d errno:%d at %d\n", |
| ret, errno, i); |
| break; |
| } |
| } |
| bulkCount = 0; |
| return 0; |
| } |
| |
| |
| /* bulk size stream count - send a bulk of messages |
| */ |
| static int |
| cmd_bulk(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int ret; |
| int on_off=0; |
| if (argc < 3) { |
| printf("bulk: expected 3 arguments\n"); |
| return -1; |
| } |
| bulkBufSize = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| bulkStream = argv[1] != NULL ? strtol(argv[1], NULL, 0) : 0; |
| bulkCount = argv[2] != NULL ? strtol(argv[2], NULL, 0) : 0; |
| if(bulkInProgress){ |
| printf("bulk: sorry bulk already in progress\n"); |
| return -1; |
| } |
| if(block_mode) { |
| /* turn on non-blocking mode */ |
| on_off = 1; |
| if(ioctl(adap->fd,FIONBIO,&block_mode) != 0) { |
| printf("IOCTL FIONBIO fails error:%d!\n",errno); |
| } |
| } |
| if(bulkBufSize > SCTP_MAX_READBUFFER){ |
| printf("bulk: size %d is to large, overriding to largest I can" |
| "handle %d\n", bulkBufSize, SCTP_MAX_READBUFFER); |
| bulkBufSize = SCTP_MAX_READBUFFER; |
| }else if (bulkBufSize <= 0) { |
| printf("bulk: size must be positive\n"); |
| return -1; |
| } |
| if (bulkCount <= 0) { |
| printf("bulk: count must be positive\n"); |
| return -1; |
| } |
| /* prepare ping buffer */ |
| /* ask for the time */ |
| if(bulkPingMode == 0){ |
| strcpy(pingBuffer,"time"); |
| ret = sctpSEND(fd,bulkStream,pingBuffer,5,SCTP_getAddr(NULL),sendOptions,payload,0); |
| strncpy(pingBuffer,"bulk",4); |
| } |
| bulkInProgress = 1; |
| checkBulkTranfer((void *)&adap->fd,NULL, 0); |
| if(bulkCount == 0){ |
| printf("bulk: bulk message are now queued\n"); |
| }else{ |
| printf("bulk: bulk transfer now in progress\n"); |
| if(block_mode) { |
| on_off = 0; |
| if(ioctl(adap->fd,FIONBIO,&block_mode) != 0) { |
| printf("IOCTL FIONBIO fails error:%d!\n",errno); |
| } |
| } |
| } |
| return 0; |
| } |
| |
| |
| /* bulkseen - display count of bulk packets seen (time resets) */ |
| static int |
| cmd_bulkstat(char *argv[], int argc) |
| { |
| int printed = 0; |
| if(bulkSeen){ |
| struct tm *timeptr; |
| timeptr = localtime(&time_started); |
| printf("bulk seen is %d\n",bulkSeen); |
| printf("last recorded time "); |
| printf("%s",asctime(timeptr)); |
| printed++; |
| } |
| if(bulkInProgress){ |
| printf("bulk count left is %d\n",bulkCount); |
| printed++; |
| } |
| if(!printed){ |
| printf("No activity\n"); |
| } |
| return 0; |
| } |
| |
| static int |
| cmd_getpaddrs(char *argv[], int argc) |
| { |
| sctp_assoc_t asocid; |
| int cnt, i; |
| struct sockaddr *sa, *addrs=NULL; |
| size_t sa_len; |
| |
| if(argc == 0) { |
| asocid = get_assoc_id(); |
| } else { |
| asocid = (sctp_assoc_t)strtoul(argv[0], NULL, 0); |
| } |
| printf("Getting addresses for assoc id 0x%x\n", (uint32_t)asocid); |
| #ifdef SOLARIS |
| cnt = sctp_getpaddrs(adap->fd, asocid, (void *)&addrs); |
| #else |
| cnt = sctp_getpaddrs(adap->fd, asocid, &addrs); |
| #endif /* SOLARIS */ |
| if (cnt > 0){ |
| sa = addrs; |
| for(i = 0; i < cnt; i++){ |
| #ifdef HAVE_SA_LEN |
| sa_len = sa->sa_len; |
| #else |
| if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in); |
| else if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in6); |
| #endif |
| printf("Address[%d] ",i); |
| SCTPPrintAnAddress(sa); |
| sa = (struct sockaddr *)((caddr_t)sa + sa_len); |
| if (sa_len == 0) |
| break; |
| } |
| sctp_freepaddrs(addrs); |
| } |
| return 0; |
| } |
| |
| static int cmd_getpdapi(char *argv[], int argc) |
| { |
| int val = 0; |
| socklen_t siz; |
| siz = sizeof(val); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PARTIAL_DELIVERY_POINT, |
| (void * )&val, &siz) != 0) { |
| printf("Failed to get value error:%d\n", errno); |
| } else { |
| printf("current pdapi point is %d\n", val); |
| } |
| return 0; |
| } |
| |
| |
| |
| static int cmd_setpdapi(char *argv[], int argc) |
| { |
| int val = 0; |
| |
| if(argc < 1) { |
| printf("Use setpdapi Value\n"); |
| return -1; |
| } |
| val = (sctp_assoc_t)strtoul(argv[0], NULL, 0); |
| printf("setting pd-api point to %d\n", val); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PARTIAL_DELIVERY_POINT, |
| &val, sizeof(val)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| return 0; |
| } |
| |
| static int cmd_seteeor(char *argv[], int argc) |
| { |
| int val = 0; |
| |
| if(argc < 1) { |
| printf("Use setpdapi Value\n"); |
| return -1; |
| } |
| val = (sctp_assoc_t)strtoul(argv[0], NULL, 0); |
| if(val) |
| printf("setting EOM mode to ON\n"); |
| else |
| printf("setting EOM mode to OFF\n"); |
| |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_EXPLICIT_EOR, |
| &val, sizeof(val)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| return 0; |
| } |
| |
| |
| static int cmd_geteeor(char *argv[], int argc) |
| { |
| int val = 0; |
| socklen_t siz; |
| siz = sizeof(val); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_EXPLICIT_EOR, |
| (void * )&val, &siz) != 0) { |
| printf("Failed to get value error:%d\n", errno); |
| } else { |
| if(val) { |
| printf("Explicit EOM mode is ON!\n"); |
| } else { |
| printf("Explicit EOM mode is OFF!\n"); |
| } |
| } |
| return 0; |
| } |
| |
| |
| |
| /* chgcookielife val - change the current assoc cookieLife */ |
| static int |
| cmd_chgcookielife(char *argv[], int argc) |
| { |
| int num; |
| struct sctp_assocparams sasoc; |
| |
| if (argc < 1) { |
| printf("defretrys: expected 1 or 2 argument\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtoul(argv[0], NULL, 0) : 0; |
| if(num == 0){ |
| printf("Sorry argument 1 must be a postive number\n"); |
| return -1; |
| } |
| memset(&sasoc,0,sizeof(sasoc)); |
| sasoc.sasoc_assoc_id = get_assoc_id(); |
| if(sasoc.sasoc_assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| /* Set in the value */ |
| sasoc.sasoc_cookie_life = num; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ASSOCINFO, &sasoc, sizeof(sasoc)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| return 0; |
| } |
| |
| |
| /* continual num - set continuous init to num times */ |
| static int |
| cmd_continual(char *argv[], int argc) |
| { |
| int num,y; |
| |
| if (argc < 1) { |
| printf("continual: expected 1 argument current cont:%d\n", |
| SCTP_getContinualInit()); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| y = SCTP_setContinualInit(num); |
| printf("continual INIT set to %d\n",y); |
| return 0; |
| } |
| |
| static int cmd_clrcwndlog(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| int buf,siz; |
| buf = 0; |
| siz = sizeof(buf); |
| |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_CLR_STAT_LOG, &buf, siz) != 0) { |
| printf("Could not clr log error %d\n",errno); |
| return 0; |
| } |
| printf("cwnd log cleared\n"); |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int cmd_cwndlog(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| char *cwnd_names[] ={ |
| "Unknown-L", |
| "Fast-rxt ", |
| "T3-timer ", |
| "Burst-lim", |
| "SlowStart", |
| "CongAvoid", |
| "Satellite", |
| "Block ", |
| "Un-Block ", |
| "Chk-Block", |
| "Del-2Strm", |
| "Del-Immed", |
| "Insert-hd", |
| "Insert-md", |
| "Insert-tl", |
| "Mark_tsn ", |
| "Express-D", |
| "Unknown-H" |
| }; |
| struct sctp_cwnd_log_req *req; |
| uint8_t buf[2048]; |
| int i; |
| socklen_t siz; |
| int idx; |
| memset(buf,0,sizeof(buf)); |
| req = (struct sctp_cwnd_log_req *)buf; |
| siz = sizeof(buf); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_GET_STAT_LOG, buf, &siz) != 0) { |
| printf("Could not get log error %d\n",errno); |
| return 0; |
| } |
| printf("num_in_log:%d returned:%d start:%d end:%d\n", |
| req->num_in_log,req->num_ret,req->start_at, |
| req->end_at); |
| for(i=0;i<req->num_ret;i++){ |
| idx = req->log[i].from; |
| if(idx < SCTP_CWND_LOG_FROM_FR) { |
| idx = 0; |
| } |
| if(idx > SCTP_STR_LOG_FROM_EXPRS_DEL) { |
| idx = SCTP_STR_LOG_FROM_EXPRS_DEL+1; |
| } |
| if(req->log[i].event_type == SCTP_LOG_EVENT_CWND) { |
| printf("%d: net:%p chg:%d cwnd:%d flight:%d by:%s\n", |
| i, |
| req->log[i].x.cwnd.net, |
| (req->log[i].x.cwnd.cwnd_augment*1024), |
| (req->log[i].x.cwnd.inflight*1024), |
| (int)req->log[i].x.cwnd.cwnd_new_value, |
| cwnd_names[idx]); |
| } else if (SCTP_LOG_EVENT_BLOCK) { |
| printf("%s: onqueue:%d sending:%d flight:%d chk:%d sendcnt:%d strmcnt:%d", |
| cwnd_names[idx], |
| (int)req->log[i].x.blk.onsb, |
| (int)req->log[i].x.blk.sndlen, |
| (int)(req->log[i].x.blk.flight_size * 1024), |
| req->log[i].x.blk.chunks_on_oque, |
| req->log[i].x.blk.send_sent_qcnt, |
| req->log[i].x.blk.stream_qcnt |
| ); |
| } else if (SCTP_LOG_EVENT_STRM) { |
| if((idx == SCTP_STR_LOG_FROM_INSERT_MD) || |
| (idx == SCTP_STR_LOG_FROM_INSERT_TL)) { |
| /* have both the new entry and |
| * the previous entry to print. |
| */ |
| printf("%s: tsn=%u sseq=%u %s tsn=%u sseq=%u", |
| cwnd_names[idx], |
| req->log[i].x.strlog.n_tsn, |
| req->log[i].x.strlog.n_sseq, |
| ((idx == SCTP_STR_LOG_FROM_INSERT_MD) ? "Before" : "After"), |
| req->log[i].x.strlog.e_tsn, |
| req->log[i].x.strlog.e_sseq |
| ); |
| }else { |
| printf("%s: tsn=%u sseq=%u", |
| cwnd_names[idx], |
| req->log[i].x.strlog.n_tsn, |
| req->log[i].x.strlog.n_sseq); |
| } |
| } |
| |
| } |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| /* defretryi num - set a new association failure threshold for initing */ |
| static int |
| cmd_defretryi(char *argv[], int argc) |
| { |
| int num; |
| struct sctp_initmsg sinit; |
| |
| if (argc < 1) { |
| printf("defretryi: expected 1 argument\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(num){ |
| memset(&sinit,0,sizeof(sinit)); |
| sinit.sinit_max_attempts = num; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_INITMSG, &sinit, sizeof(sinit)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| }else{ |
| printf("Sorry argument must be at least 1\n"); |
| } |
| return 0; |
| } |
| |
| |
| /* defretrys num - set a new association failure threshold for sending |
| */ |
| static int |
| cmd_defretrys(char *argv[], int argc) |
| { |
| int num; |
| struct sctp_assocparams sasoc; |
| |
| if (argc < 1) { |
| printf("defretrys: expected 1 or 2 argument\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(num == 0){ |
| printf("Sorry argument 1 must be a postive number\n"); |
| return -1; |
| } |
| memset(&sasoc,0,sizeof(sasoc)); |
| /* Set in the value */ |
| sasoc.sasoc_asocmaxrxt = num; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ASSOCINFO, &sasoc, sizeof(sasoc)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| /* Now set in the retry's for the assoc */ |
| return 0; |
| } |
| |
| |
| /* defrwnd num - set the default rwnd of the SCTP |
| */ |
| static int |
| cmd_defrwnd(char *argv[], int argc) |
| { |
| /* int fd = adap->fd;*/ |
| int num,optlen; |
| |
| if (argc < 1) { |
| printf("defrwnd: expected 1 argument\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtoul(argv[0], NULL, 0) : 0; |
| optlen = sizeof(num); |
| if(num > 1500){ |
| setsockopt(adap->fd, SOL_SOCKET, SO_RCVBUF, &num, optlen); |
| } |
| return 0; |
| } |
| |
| |
| /* delip address [how] - delete ip address where how is the mask/action to pass |
| */ |
| static int |
| cmd_delip(char *argv[], int argc) |
| { |
| /* |
| int fd = adap->fd; |
| char *address; |
| struct addrinfo hints, *res; |
| int how, ret; |
| |
| if (argc < 1) { |
| printf("delip: expected at least 1 argument\n"); |
| return -1; |
| } |
| address = argv[0]; |
| how = argv[1] != NULL ? strtol(argv[1], NULL, 0) : 0; |
| |
| bzero(&hints, sizeof(hints)); |
| hints.ai_flags = AI_NUMERICHOST; |
| */ |
| |
| /* |
| ret = getaddrinfo(address, NULL, &hints, &res); |
| if (ret != 0) { |
| printf("delip: getaddrinfo: %s\n", gai_strerror(ret)); |
| return -1; |
| } |
| printf("delip: deleting IP address %s, action 0x%x\n", address, how); |
| ret = sctpDELIPADDRESS(fd, res->ai_addr, SCTP_getAddr(), how); |
| if (ret != 1) { |
| printf("delip: failed, return value: %d\n", ret); |
| } else { |
| printf("delip: success\n"); |
| } |
| freeaddrinfo(res); |
| return ret != 1 ? -1 : 0; |
| */ |
| return 0; |
| } |
| |
| |
| /* doheartbeat - preform a on demand HB |
| */ |
| static int |
| cmd_doheartbeat(char *argv[], int argc) |
| { |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| struct sctp_paddrparams sp; |
| int ret; |
| int siz; |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| sp.spp_hbinterval = 0xffffffff; |
| /* Disable this so we don't change it */ |
| |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| printf("Request returns %d\n",ret); |
| return 0; |
| } |
| |
| |
| /* getcurcookielife - display current assoc cookieLife |
| */ |
| static int |
| cmd_getcwndpost(char *argv[], int argc) |
| { |
| printf("Command no longer supported\n"); |
| return 0; |
| } |
| |
| static int |
| cmd_getcurcookielife(char *argv[], int argc) |
| { |
| socklen_t siz; |
| struct sctp_assocparams sasoc; |
| siz = sizeof(sasoc); |
| memset(&sasoc,0,sizeof(sasoc)); |
| /* Set in the value */ |
| sasoc.sasoc_assoc_id = get_assoc_id(); |
| if(sasoc.sasoc_assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| |
| if(getsockopt(adap->fd, IPPROTO_SCTP, SCTP_ASSOCINFO, &sasoc, &siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return -1; |
| } |
| printf("Association cookie life is set to %d\n", |
| sasoc.sasoc_cookie_life); |
| return 0; |
| } |
| |
| |
| /* getdefcookielife - display default cookie life |
| */ |
| static int |
| cmd_getdefcookielife(char *argv[], int argc) |
| { |
| socklen_t siz; |
| struct sctp_assocparams sasoc; |
| |
| siz = sizeof(sasoc); |
| memset(&sasoc,0,sizeof(sasoc)); |
| /* Set in the value */ |
| if(getsockopt(adap->fd, IPPROTO_SCTP, SCTP_ASSOCINFO, &sasoc, &siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return -1; |
| } |
| printf("Endpoint cookie life is set to %d\n", |
| sasoc.sasoc_cookie_life); |
| return 0; |
| } |
| |
| |
| /* gethbdelay - get the hb delay |
| */ |
| static int |
| cmd_gethbdelay(char *argv[], int argc) |
| { |
| struct sctp_paddrparams sp; |
| struct sockaddr *sa; |
| socklen_t sa_len = 0; |
| socklen_t siz; |
| int useaddr; |
| |
| useaddr = 1; |
| if(argc == 1){ |
| if(strcmp("ep",argv[0]) == 0){ |
| useaddr = 0; |
| } |
| } |
| siz = sizeof(sp); |
| if(useaddr) |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| if(useaddr) |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| if(getsockopt(adap->fd, IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| if(sp.spp_assoc_id) { |
| printf("Current failure threshold is %d\n",sp.spp_pathmaxrxt); |
| printf("Current HB interval is %d\n",sp.spp_hbinterval); |
| printf("Assoc id is 0x%x\n",(uint32_t)sp.spp_assoc_id); |
| } else { |
| printf("EP default failure threshold is %d\n",sp.spp_pathmaxrxt); |
| printf("EP default HB interval is %d\n",sp.spp_hbinterval); |
| } |
| return 0; |
| } |
| |
| static int cmd_getpcbinfo(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_pcbinfo optval; |
| socklen_t siz; |
| |
| siz = sizeof(optval); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PCB_STATUS, &optval, &siz) != 0) { |
| printf("Can't get PCB status on socket err:%d!\n",errno); |
| }else{ |
| printf("Number of SCTP endpoints is %d\n",optval.ep_count); |
| printf("Number of SCTP associations is %d\n",optval.asoc_count); |
| printf("Number of SCTP laddr's in use is %d\n",optval.laddr_count); |
| printf("Number of SCTP raddr's in use is %d\n",optval.raddr_count); |
| printf("Number of SCTP chunks in use is %d\n",optval.chk_count); |
| printf("Number of SCTP readq in use is %d\n",optval.readq_count); |
| printf("Number of SCTP str-outq in use is %d\n", optval.stream_oque); |
| printf("Number of SCTP free_chunks %d\n",optval.free_chunks); |
| } |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int |
| cmd_clrstat(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctpstat stat, zerostat; |
| size_t len = sizeof(struct sctpstat); |
| |
| memset(&zerostat, 0, sizeof(struct sctpstat)); |
| if (sysctlbyname("net.inet.sctp.stats", &stat, &len, &zerostat, len) < 0) { |
| if (errno == EPERM) |
| printf("Error: You need to have root previledges to reset the stat.\n"); |
| else |
| printf("Error %d (%s) could not reset the stat\n", errno, strerror(errno)); |
| } else { |
| printf("stats reseted.\n"); |
| } |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int |
| cmd_getstat(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctpstat stat; |
| size_t len = sizeof(struct sctpstat); |
| unsigned int cnt = 0; |
| |
| if (sysctlbyname("net.inet.sctp.stats", &stat, &len, NULL, 0) < 0) { |
| printf("Error %d (%s) could not get the stat\n", errno, strerror(errno)); |
| return(0); |
| } |
| |
| #define p(f, n) \ |
| printf("%-10.10s=%08X%s", n, stat.f, ((cnt++&3)==3)?"\n":" ") |
| #define nl(n) \ |
| do { \ |
| printf("%s%s\n", ((cnt&3)==0)?"":"\n", n);\ |
| cnt = 0;\ |
| } while(0) |
| |
| nl("MIB"); |
| p(sctps_currestab, "currentestab"); |
| p(sctps_activeestab, "activeestab"); |
| p(sctps_restartestab, "restartestab"); |
| p(sctps_collisionestab, "collisionestab"); |
| p(sctps_passiveestab, "passiveestab"); |
| p(sctps_aborted, "aborted"); |
| p(sctps_shutdown, "shutdown"); |
| p(sctps_outoftheblue, "outoftheblue"); |
| p(sctps_checksumerrors, "checksumerrors"); |
| p(sctps_outcontrolchunks, "outcontrolchunks"); |
| p(sctps_outorderchunks, "outorderchunks"); |
| p(sctps_outunorderchunks, "outunorderchunks"); |
| p(sctps_incontrolchunks, "incontrolchunks"); |
| p(sctps_inorderchunks, "inorderchunks"); |
| p(sctps_inunorderchunks, "inunorderchunks"); |
| p(sctps_fragusrmsgs, "fragusrmsg"); |
| p(sctps_reasmusrmsgs, "reasmusrmsg"); |
| p(sctps_outpackets, "outpackets"); |
| p(sctps_inpackets, "inpackets"); |
| nl("RECV"); |
| p(sctps_recvpackets, "packets"); |
| p(sctps_recvdatagrams, "datagrams"); |
| p(sctps_recvpktwithdata, "pktwithdata"); |
| p(sctps_recvsacks, "sacks"); |
| p(sctps_recvdata, "data"); |
| p(sctps_recvdupdata, "dupdata"); |
| p(sctps_recvheartbeat, "heartbeat"); |
| p(sctps_recvheartbeatack, "heartbeatack"); |
| p(sctps_recvecne, "ecne"); |
| p(sctps_recvauth, "auth"); |
| p(sctps_recvauthmissing, "authmissing"); |
| p(sctps_recvivalhmacid, "ivalhmacid"); |
| p(sctps_recvivalkeyid, "ivalkeyid"); |
| p(sctps_recvauthfailed, "authfailed"); |
| p(sctps_recvexpress, "expressd"); |
| p(sctps_recvexpressm, "expressdm"); |
| p(sctps_recvnocrc, "recvnocrc"); |
| p(sctps_recvswcrc, "recvswcrc"); |
| p(sctps_recvhwcrc, "recvhwcrc"); |
| nl("SEND"); |
| p(sctps_sendpackets, "packets"); |
| p(sctps_sendsacks, "sacks"); |
| p(sctps_senddata, "data"); |
| p(sctps_sendretransdata, "retransdata"); |
| p(sctps_sendfastretrans, "fastretrans"); |
| p(sctps_sendmultfastretrans, "multfastretrans"); |
| p(sctps_sendheartbeat, "heartbeat"); |
| p(sctps_sendecne, "ecne"); |
| p(sctps_sendauth, "auth"); |
| p(sctps_senderrors, "ifp:io_errors"); |
| p(sctps_sendnocrc, "sendnocrc"); |
| p(sctps_sendswcrc, "sendswcrc"); |
| p(sctps_sendhwcrc, "sendhwcrc"); |
| |
| nl("PDRP"); |
| p(sctps_pdrpfmbox, "fmbox"); |
| p(sctps_pdrpfehos, "fehos"); |
| p(sctps_pdrpmbda, "mbda"); |
| p(sctps_pdrpmbct, "mbct"); |
| p(sctps_pdrpbwrpt, "bwrpt"); |
| p(sctps_pdrpcrupt, "crupt"); |
| p(sctps_pdrpnedat, "nedat"); |
| p(sctps_pdrppdbrk, "pdbrk"); |
| p(sctps_pdrptsnnf, "tsnnf"); |
| p(sctps_pdrpdnfnd, "dnfnd"); |
| p(sctps_pdrpdiwnp, "diwnp"); |
| p(sctps_pdrpdizrw, "dizrw"); |
| p(sctps_pdrpbadd, "badd"); |
| p(sctps_pdrpmark, "mark"); |
| nl("TIMEOUT"); |
| p(sctps_timoiterator, "iterator"); |
| p(sctps_timodata, "data"); |
| p(sctps_timowindowprobe, "windowprobe"); |
| p(sctps_timoinit, "init"); |
| p(sctps_timosack, "sack"); |
| p(sctps_timoshutdown, "shutdown"); |
| p(sctps_timoheartbeat, "heartbeat"); |
| p(sctps_timocookie, "cookie"); |
| p(sctps_timosecret, "secret"); |
| p(sctps_timopathmtu, "pathmtu"); |
| p(sctps_timoshutdownack, "shutdownack"); |
| p(sctps_timoshutdownguard, "shutdownguard"); |
| p(sctps_timostrmrst, "strmrst"); |
| p(sctps_timoasconf, "asconf"); |
| p(sctps_timoautoclose, "autoclose"); |
| p(sctps_timoassockill, "assockill"); |
| p(sctps_timoinpkill, "inpkill"); |
| nl("OTHER"); |
| p(sctps_hdrops, "hdrops"); |
| p(sctps_badsum, "badsum"); |
| p(sctps_noport, "noport"); |
| p(sctps_badvtag, "badvtag"); |
| p(sctps_badsid, "badsid"); |
| p(sctps_nomem, "nomem"); |
| p(sctps_fastretransinrtt, "fastretransinrtt"); |
| p(sctps_markedretrans, "markedretrans"); |
| p(sctps_naglesent, "naglesent"); |
| p(sctps_naglequeued, "naglequeued"); |
| p(sctps_maxburstqueued, "maxburstqueued"); |
| p(sctps_ifnomemqueued, "ifnomemqueued"); |
| p(sctps_windowprobed, "windowprobed"); |
| p(sctps_lowlevelerr, "lowlevelerr"); |
| p(sctps_lowlevelerrusr, "lowlevelerrusr"); |
| p(sctps_datadropchklmt, "datadropchklmt"); |
| p(sctps_datadroprwnd, "datadroprwnd"); |
| p(sctps_ecnereducedcwnd, "ecnereducedcwnd"); |
| p(sctps_vtagexpress, "vtagexpress"); |
| p(sctps_vtagbogus, "vtagbogus"); |
| p(sctps_primary_randry, "pri.randry"); |
| p(sctps_cmt_randry, "cmt.randry"); |
| p(sctps_slowpath_sack, "slow_sacks"); |
| p(sctps_wu_sacks_sent, "wup_sack_s"); |
| p(sctps_sends_with_flags, "w_sinfo_fl"); |
| p(sctps_sends_with_unord, "w_unorder"); |
| p(sctps_sends_with_eof, "w_eof"); |
| p(sctps_sends_with_abort, "w_abort"); |
| p(sctps_read_peeks, "peek_reads"); |
| p(sctps_cached_chk, "free_chk_u"); |
| p(sctps_cached_strmoq, "free_rqs_u"); |
| p(sctps_left_abandon, "abandoned"); |
| p(sctps_send_burst_avoid, "snd_bua"); |
| p(sctps_send_cwnd_avoid, "snd_cwa"); |
| nl(""); |
| #undef p |
| #undef nl |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int |
| cmd_getassocstat(char *argv[], int argc) |
| { |
| #if defined(__APPLE__) || defined(__FreeBSD__) |
| #define ADDRSTRLEN 46 |
| size_t len; |
| caddr_t buf; |
| unsigned int offset; |
| struct xsctp_inpcb *xinp; |
| struct xsctp_tcb *xstcb; |
| struct xsctp_laddr *xladdr; |
| struct xsctp_raddr *xraddr; |
| char buffer[ADDRSTRLEN]; |
| sa_family_t family; |
| void *addr; |
| |
| len = 0; |
| if (sysctlbyname("net.inet.sctp.assoclist", 0, &len, 0, 0) < 0) { |
| printf("Error %d (%s) could not get the assoclist\n", errno, strerror(errno)); |
| return(0); |
| } |
| if ((buf = (caddr_t)malloc(len)) == 0) { |
| printf("malloc %lu bytes failed.\n", (long unsigned)len); |
| return(0); |
| } |
| if (sysctlbyname("net.inet.sctp.assoclist", buf, &len, 0, 0) < 0) { |
| printf("Error %d (%s) could not get the assoclist\n", errno, strerror(errno)); |
| free(buf); |
| return(0); |
| } |
| offset = 0; |
| xinp = (struct xsctp_inpcb *)(buf + offset); |
| while (xinp->last == 0) { |
| printf("\nEndpoint with port=%d, flags=%x, features=%x, FragPoint=%u, Msgs(R/S/SF)=%u/%u/%u\n", |
| xinp->local_port, xinp->flags, xinp->features, xinp->fragmentation_point, xinp->total_recvs, xinp->total_sends, xinp->total_nospaces); |
| offset += sizeof(struct xsctp_inpcb); |
| printf("\tLocal addresses:"); |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| while (xladdr->last == 0) { |
| family = xladdr->address.sin.sin_family; |
| switch (family) { |
| case AF_INET: |
| addr = (void *)&xladdr->address.sin.sin_addr; |
| break; |
| case AF_INET6: |
| addr = (void *)&xladdr->address.sin6.sin6_addr; |
| break; |
| default: |
| printf("Unknown family: %d.\n", family); |
| break; |
| } |
| printf(" %s", inet_ntop(family, addr, buffer, ADDRSTRLEN)); |
| offset += sizeof(struct xsctp_laddr); |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_laddr); |
| printf(".\n"); |
| |
| xstcb = (struct xsctp_tcb *)(buf + offset); |
| while (xstcb->last == 0) { |
| xstcb = (struct xsctp_tcb *)(buf + offset); |
| printf("\tAssociation towards port=%d, state=%d, Streams(I/O)=(%u/%u), HBInterval=%u, MTU=%u, Msgs(R/S)=(%u/%u), \n\t\tTSN(init/high/cum/cumack)=(%x/%x/%x/%x),\n\t\tTag(L/R)=(%x/%x).\n", |
| xstcb->remote_port, xstcb->state, xstcb->in_streams, xstcb->out_streams, xstcb->heartbeat_interval, xstcb->mtu, xstcb->total_recvs, xstcb->total_sends, xstcb->initial_tsn, xstcb->highest_tsn, xstcb->cumulative_tsn, xstcb->cumulative_tsn_ack, xstcb->local_tag, xstcb->remote_tag); |
| offset += sizeof(struct xsctp_tcb); |
| |
| printf("\t\tLocal addresses:"); |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| while (xladdr->last == 0) { |
| family = xladdr->address.sin.sin_family; |
| switch (family) { |
| case AF_INET: |
| addr = (void *)&xladdr->address.sin.sin_addr; |
| break; |
| case AF_INET6: |
| addr = (void *)&xladdr->address.sin6.sin6_addr; |
| break; |
| default: |
| printf("Unknown family: %d.\n", family); |
| break; |
| } |
| printf(" %s", inet_ntop(family, addr, buffer, ADDRSTRLEN)); |
| offset += sizeof(struct xsctp_laddr); |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_laddr); |
| printf(".\n"); |
| |
| xraddr = (struct xsctp_raddr *)(buf + offset); |
| while (xraddr->last == 0) { |
| family = xraddr->address.sin.sin_family; |
| switch (family) { |
| case AF_INET: |
| addr = (void *)&xraddr->address.sin.sin_addr; |
| break; |
| case AF_INET6: |
| addr = (void *)&xraddr->address.sin6.sin6_addr; |
| break; |
| } |
| printf("\t\tPath towards %s, Active=%d, Confirmed=%d, MTU=%u, HBEnabled=%u, RTO=%u, CWND=%u, Flightsize=%u, ErrorCounter=%u.\n", |
| inet_ntop(family, addr, buffer, ADDRSTRLEN), xraddr->active, xraddr->confirmed, xraddr->mtu, xraddr->heartbeat_enabled, xraddr->rto, xraddr->cwnd, xraddr->flight_size, xraddr->error_counter); |
| offset += sizeof(struct xsctp_raddr); |
| xraddr = (struct xsctp_raddr *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_raddr); |
| xstcb = (struct xsctp_tcb *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_tcb); |
| xinp = (struct xsctp_inpcb *)(buf + offset); |
| } |
| free((void *)buf); |
| return(0); |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| /* getprimary - tells which net number is primary */ |
| static int |
| cmd_getprimary(char *argv[], int argc) |
| { |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| #ifdef linux |
| struct sctp_prim prim; |
| #else |
| struct sctp_setprim prim; |
| #endif |
| socklen_t siz; |
| |
| memset(&prim,0,sizeof(prim)); |
| sa = SCTP_getAddr(&sa_len); |
| siz = sizeof(prim); |
| memcpy(&prim.ssp_addr, (caddr_t)sa, sa_len); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PRIMARY_ADDR,&prim,&siz) != 0) { |
| printf("Can't get primary address error:%d\n",errno); |
| return -1; |
| } |
| printf("Primary address is "); |
| SCTPPrintAnAddress((struct sockaddr *)&prim.ssp_addr); |
| return 0; |
| } |
| |
| static int |
| cmd_getroute(char *argv[], int argc) |
| { |
| printf("code nolonger supported (for now :>)\n"); |
| return(0); |
| } |
| /* getrtt - Return the RTO of the current default address of the assoc |
| */ |
| |
| |
| static int |
| cmd_getrtt(char *argv[], int argc) |
| { |
| struct sctp_paddrinfo so; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| socklen_t siz; |
| |
| sa = SCTP_getAddr(&sa_len); |
| memset(&so,0,sizeof(so)); |
| memcpy((caddr_t)&so.spinfo_address, sa, sa_len); |
| siz = sizeof(so); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_GET_PEER_ADDR_INFO, &so, &siz) != 0) { |
| printf("Failed to get dest info err:%d\n",errno); |
| return 0; |
| } |
| printf("Destination state is 0x%x\n",so.spinfo_state); |
| printf("Destination RTO is %d\n",so.spinfo_rto); |
| printf("Destination srtt is %d\n",so.spinfo_srtt); |
| printf("Destination cwnd is %d\n",so.spinfo_cwnd); |
| return 0; |
| } |
| |
| static int |
| cmd_getsnd(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_sockstat so; |
| socklen_t siz; |
| |
| if(argc != 1){ |
| printf("Sorry - getsnd requires associd argument\n"); |
| return -1; |
| } |
| memset(&so,0,sizeof(so)); |
| so.ss_assoc_id = (sctp_assoc_t)strtoul(argv[0],NULL,0); |
| siz = sizeof(so); |
| if(getsockopt(adap->fd,IPPROTO_SCTP,SCTP_GET_SNDBUF_USE, |
| &so, &siz) != 0) { |
| printf("Failed to get dest info err:%d\n",errno); |
| return 0; |
| } |
| printf("For association 0x%x\n",(uint32_t)so.ss_assoc_id); |
| printf("Total sndbuf %d\n",(int)so.ss_total_sndbuf); |
| printf("Total in recvbuf %d\n",(int)so.ss_total_recv_buf); |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| #if defined(__BSD_SCTP_STACK__) |
| static int |
| print_peer_addr_info(struct sctp_paddrinfo *so) |
| { |
| struct sctp_paddrparams sp; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| socklen_t siz; |
| |
| siz = sizeof(sp); |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| memset(so,0,sizeof(so)); |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| memcpy((caddr_t)&so->spinfo_address, sa, sa_len); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| siz = sizeof(struct sctp_paddrinfo); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_GET_PEER_ADDR_INFO, so, &siz) != 0) { |
| printf("Failed to get dest info err:%d\n",errno); |
| return 0; |
| } |
| printf("Current fail thresh is %d\n",sp.spp_pathmaxrxt); |
| printf("Current HB interval is %d\n",sp.spp_hbinterval); |
| printf("Destination state is 0x%x\n",so->spinfo_state); |
| printf("Destination RTO is %d\n",so->spinfo_rto); |
| printf("Destination srtt is %d\n",so->spinfo_srtt); |
| printf("Destination cwnd is %d\n",so->spinfo_cwnd); |
| printf("Assoc id is 0x%x\n",(uint32_t)sp.spp_assoc_id); |
| /* Disable this so we don't change it */ |
| return(0); |
| } |
| #endif |
| |
| /* heart on/off - Turn HB on or off to the destination */ |
| static int |
| cmd_heart(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_paddrparams sp; |
| struct sctp_paddrinfo so; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| socklen_t siz; |
| char *bool; |
| |
| siz = sizeof(sp); |
| if (argc != 1) { |
| printf("heart: expected 1 argument\n"); |
| return -1; |
| } |
| bool = argv[0]; |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| memset(&so,0,sizeof(so)); |
| |
| if(strcmp(bool, "on") == 0){ |
| print_peer_addr_info(&so); |
| if((so.spinfo_state & SCTP_ADDR_NOHB) == 0){ |
| siz = sizeof(sp); |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| if(sp.spp_hbinterval == 0){ |
| /* Set to a postive value */ |
| sp.spp_hbinterval = 2000; |
| sp.spp_flags = SPP_HB_ENABLE; |
| } |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| } else { |
| printf("Heartbeat is already on\n"); |
| } |
| }else if(strcmp(bool, "off") == 0) { |
| print_peer_addr_info(&so); |
| if(so.spinfo_state & SCTP_ADDR_NOHB){ |
| printf("Destination is already NOT heartbeating\n"); |
| }else{ |
| sp.spp_flags = SPP_HB_DISABLE; |
| siz = sizeof(sp); |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| } |
| }else if(strcmp(bool, "alloff") == 0) { |
| memset(&sp,0,sizeof(sp)); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| if(sp.spp_hbinterval){ |
| memset((caddr_t)&sp,0,sizeof(sp)); |
| sp.spp_flags = SPP_HB_DISABLE; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| }else{ |
| printf("All heartbeats already off\n"); |
| } |
| memset(&sp,0,sizeof(sp)); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| printf("Current fail thresh is %d\n",sp.spp_pathmaxrxt); |
| printf("Current HB interval is %d\n",sp.spp_hbinterval); |
| printf("Assoc id is 0x%x\n",(uint32_t)sp.spp_assoc_id); |
| }else if(strcmp(bool, "allon") == 0) { |
| memset((caddr_t)&sp.spp_address,0,sizeof(sp.spp_address)); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| if(sp.spp_hbinterval){ |
| printf("Heartbeat already on and set to %d\n",sp.spp_hbinterval); |
| }else{ |
| /* set to the default 30 seconds */ |
| memset((caddr_t)&sp.spp_address,0,sizeof(sp.spp_address)); |
| sp.spp_hbinterval = 2000; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| } |
| memset(&sp,0,sizeof(sp)); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| printf("Current fail thresh is %d\n",sp.spp_pathmaxrxt); |
| printf("Current HB interval is %d\n",sp.spp_hbinterval); |
| printf("Assoc id is 0x%x\n",(uint32_t)sp.spp_assoc_id); |
| }else{ |
| printf("heart: expected on or off allon or alloff\n"); |
| return -1; |
| } |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| /* heartdelay time - Add number of seconds + RTO to hb interval */ |
| static int |
| cmd_heartdelay(char *argv[], int argc) |
| { |
| struct sctp_paddrparams sp; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| socklen_t siz; |
| int val; |
| int setaddr; |
| |
| setaddr = 1; |
| siz = sizeof(sp); |
| if (argc < 1) { |
| printf("heartdelay: expected 1 argument\n"); |
| return -1; |
| } |
| if(argc == 2){ |
| if(strcmp(argv[1],"ep") == 0){ |
| printf("I will set it to the base ep\n"); |
| setaddr = 0; |
| }else{ |
| printf("Don't understand qualifier %s\n",argv[1]); |
| return -1; |
| } |
| } |
| val = strtol(argv[0],NULL,0); |
| printf("val of hb set to %d\n",val); |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| if(setaddr) |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get HB info err:%d\n",errno); |
| return 0; |
| } |
| printf("Current HB interval is %d\n",sp.spp_hbinterval); |
| /* Disable this so we don't change it */ |
| sp.spp_pathmaxrxt = 0; |
| if (setaddr != 1) |
| memset((caddr_t)&sp.spp_address,0,sizeof(sp.spp_address)); |
| sp.spp_hbinterval = val; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, siz) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| return 0; |
| } |
| |
| |
| /* help [cmd] - display help for cmd, or for all the commands if no cmd specified |
| */ |
| static int |
| cmd_help(char *argv[], int argc) |
| { |
| int i, printed; |
| char *cmdname; |
| struct command *cmd; |
| |
| printed = 0; |
| cmdname = argv[0]; |
| if (cmdname != NULL) { |
| if ( (cmd = find_command(cmdname)) != NULL) { |
| printf("%s\n", cmd->co_desc); |
| } else { |
| printf("help: no match for `%s'. Commands are:", cmdname); |
| for (i = 0; commands[i].co_name != NULL; i++) { |
| printf("%s", printed % 3 == 0 ? "\n" : ""); |
| printf("%-20.20s", commands[i].co_name); |
| printed++; |
| } |
| printf("\n"); |
| } |
| } else { |
| for (i = 0; commands[i].co_name != NULL; i++) { |
| printf("%s\n", commands[i].co_desc); |
| } |
| } |
| return 0; |
| } |
| |
| static int |
| cmd_bulkstop(char *argv[], int argc) |
| { |
| bulkCount = 0; |
| return 0; |
| } |
| |
| /* hulkstart filename - start the hulk hogan process */ |
| static int |
| cmd_hulkstart(char *argv[], int argc) |
| { |
| char *filename; |
| |
| if (argc < 1) { |
| printf("hulkstart: Gak, no file name\n"); |
| return -1; |
| } |
| filename = argv[0]; |
| /* XXX [MM] symlink attack */ |
| hulkfile = fopen(filename, "w+"); |
| if(hulkfile != NULL){ |
| printf("hulk scheduler begun\n"); |
| dist_TimerStart(dist, |
| SCTPdataTimerTicks, |
| 0,period,(void *)NULL,(void *)&adap->fd); |
| }else{ |
| printf("Can't open file err:%d for file '%s'\n", |
| errno,filename); |
| return -1; |
| } |
| return 0; |
| } |
| |
| |
| /* hulkstop - stop the hulk hogan process */ |
| static int |
| cmd_hulkstop(char *argv[], int argc) |
| { |
| curSeq = 0; |
| if(hulkfile != NULL) |
| fclose(hulkfile); |
| hulkfile = NULL; |
| dist_TimerStop(dist, |
| SCTPdataTimerTicks, |
| (void *)NULL,(void *)&adap->fd, 0); |
| return 0; |
| } |
| |
| |
| /* initmultping - init contexts for a fast test */ |
| static int |
| cmd_initmultping(char *argv[], int argc) |
| { |
| /* int fd = adap->fd;*/ |
| |
| /* initPingPongTable(sctpGETNUMOUTSTREAMS(fd,SCTP_getAddr()));*/ |
| /* printf("%d ping pong contexts are defined \n", pingPongsDefined);*/ |
| /* printf("Type startmultping to proceed\n");*/ |
| return 0; |
| } |
| |
| |
| /* inqueue - report inqueue counts |
| */ |
| static int |
| cmd_inqueue(char *argv[], int argc) |
| { |
| /* int fd = adap->fd;*/ |
| |
| /* printf("Outbound queue count to dest = %d\n", |
| sctpHOWMANYINQUEUE(m,SCTP_getAddr())); |
| printf("Inbound queue count = %d\n",sctpHOWMANYINBOUND(m)); |
| */ |
| return 0; |
| } |
| |
| |
| /* multping size stream count blockafter sec |
| * - add a ping pong context and block after <blockafter> instances for |
| * <sec> seconds |
| */ |
| static int |
| cmd_multping(char *argv[], int argc) |
| { |
| int i; |
| int myPingCount, myPingStream, myBlockAfter, myBlockDuring; |
| |
| if (argc != 5) { |
| printf("multping: expected 5 arguments\n"); |
| return -1; |
| } |
| pingBufSize = strtol(argv[0], NULL, 0); |
| myPingStream = strtol(argv[1], NULL, 0); |
| myPingCount = strtol(argv[2], NULL, 0); |
| myBlockAfter = strtol(argv[3], NULL, 0); |
| myBlockDuring = strtol(argv[4], NULL, 0); |
| |
| if(pingBufSize <= 0 || pingBufSize > SCTP_MAX_READBUFFER){ |
| printf("size %d out of range, setting to largest I can handle %d\n", |
| pingBufSize,SCTP_MAX_READBUFFER); |
| pingBufSize = SCTP_MAX_READBUFFER; |
| } |
| if(myPingStream < 0 || myPingStream > (MAX_PING_PONG_CONTEXTS - 1)){ |
| printf("stream %d out of range, setting to largest I can handle %d\n", |
| myPingStream, MAX_PING_PONG_CONTEXTS - 1); |
| myPingStream = MAX_PING_PONG_CONTEXTS - 1; |
| } |
| if(myPingCount <= 0){ |
| printf("Invalid ping pong count\n"); |
| return -1; |
| } |
| if(myBlockAfter <= 0){ |
| printf("Invalid block after\n"); |
| return -1; |
| } |
| if(myBlockDuring <= 0){ |
| printf("Invalid block during\n"); |
| return -1; |
| |
| } |
| |
| for(i=0;i<MAX_PING_PONG_CONTEXTS;i++){ |
| if(pingPongTable[i].stream == -1){ |
| pingPongTable[i].stream = myPingStream; |
| pingPongTable[i].counter = 0; |
| pingPongTable[i].nbRequests = myPingCount; |
| pingPongTable[i].blockAfter = myBlockAfter; |
| pingPongTable[i].blockDuring = myBlockDuring; |
| pingPongTable[i].blockTime = 0; |
| break; |
| } |
| } |
| pingPongsDefined++; |
| printf("%d ping pong contexts are defined\n", pingPongsDefined); |
| printf("Type startmultping to proceed\n"); |
| |
| return 0; |
| } |
| |
| static char * |
| sctp_network_state(uint32_t state) |
| { |
| static char str_buf[256]; |
| #if defined(__BSD_SCTP_STACK__) |
| int len; |
| |
| str_buf[0] = 0; |
| if(state & SCTP_ADDR_REACHABLE) { |
| strcat(str_buf,"Reachable|"); |
| } |
| if(state & SCTP_ADDR_NOHB) { |
| strcat(str_buf,"NO-HB|"); |
| } |
| if(state & SCTP_ADDR_BEING_DELETED) { |
| strcat(str_buf,"Being-Deleted|"); |
| } |
| if(state & SCTP_ADDR_NOT_IN_ASSOC) { |
| strcat(str_buf,"Not-In-Assoc|"); |
| } |
| if(state & SCTP_ADDR_OUT_OF_SCOPE) { |
| strcat(str_buf,"Out-Of-Scope|"); |
| } |
| if(state & SCTP_ADDR_UNCONFIRMED) { |
| strcat(str_buf,"UNCONFIRMED"); |
| } |
| len = strlen(str_buf); |
| if(str_buf[(len-1)] == '|') |
| str_buf[(len-1)] = 0; |
| #else |
| snprintf(str_buf, sizeof(str_buf)-1, "0x%0x", state); |
| #endif |
| return(str_buf); |
| } |
| |
| |
| /* netstats - return all network stats */ |
| static int |
| cmd_netstats(char *argv[], int argc) |
| { |
| int numnets, i; |
| sctp_assoc_t assoc_id; |
| struct sockaddr *sa, *addrs; |
| socklen_t sa_len = 0; |
| socklen_t siz; |
| |
| /* optional assoc_id parameter */ |
| if (argc == 1) { |
| assoc_id = (sctp_assoc_t)strtoul(argv[0], NULL, 0); |
| } else if (argc > 1) { |
| printf("netstats: can only take one optional argument (assoc_id)\n"); |
| return (-1); |
| } else { |
| assoc_id = get_assoc_id(); |
| if(assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| } |
| |
| printf("Setting on assoc id 0x%x\n",(uint32_t)assoc_id); |
| /* Now we get the association parameters so we know how |
| * many networks there are. |
| */ |
| #ifdef SOLARIS |
| numnets = sctp_getpaddrs(adap->fd, assoc_id, (void *)&addrs); |
| #else |
| numnets = sctp_getpaddrs(adap->fd, assoc_id, &addrs); |
| #endif /* SOLARIS */ |
| if (numnets < 0) { |
| printf("Can't get the peer addresses\n"); |
| return -1; |
| } |
| printf("There are %d destinations to the peer\n",numnets); |
| sa = addrs; |
| for(i=0; i<numnets; i++){ |
| struct sctp_paddrinfo addrwewant; |
| #ifdef HAVE_SA_LEN |
| sa_len = sa->sa_len; |
| #else |
| if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in); |
| else if (sa->sa_family == AF_INET6) |
| sa_len = sizeof(struct sockaddr_in6); |
| #endif |
| memcpy(&addrwewant.spinfo_address, sa, sa_len); |
| addrwewant.spinfo_assoc_id = assoc_id; |
| siz = sizeof(addrwewant); |
| printf("Address[%d]:\n",i); |
| SCTPPrintAnAddress(sa); |
| /* Now get its specific info */ |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_GET_PEER_ADDR_INFO, |
| &addrwewant,&siz) != 0){ |
| printf("Failed to gather information, err:%d\n",errno); |
| }else{ |
| printf("State:%s,",sctp_network_state((uint32_t)addrwewant.spinfo_state)); |
| printf("cwnd:%d,",addrwewant.spinfo_cwnd); |
| printf("srtt:%d,",addrwewant.spinfo_srtt); |
| printf("rto:%d\n",addrwewant.spinfo_rto); |
| } |
| sa = (struct sockaddr *)((caddr_t)sa + sa_len); |
| } |
| sctp_freepaddrs(addrs); |
| return 0; |
| } |
| |
| |
| /* ping size stream count - play ping pong */ |
| static int |
| cmd_ping(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| |
| if(pingPongCount){ |
| printf("Sorry ping-pong already in progress\n"); |
| return -1; |
| } |
| if (argc != 3) { |
| printf("ping: expected 3 arguments\n"); |
| return -1; |
| } |
| pingBufSize = strtol(argv[0], NULL, 0); |
| pingStream = strtol(argv[1], NULL, 0); |
| pingPongCount = strtol(argv[2], NULL, 0); |
| if(pingBufSize > SCTP_MAX_READBUFFER){ |
| printf("%d is to large, override to largest I can handle %d\n", |
| pingBufSize,SCTP_MAX_READBUFFER); |
| pingBufSize = SCTP_MAX_READBUFFER; |
| } |
| /* XXX no check for pingStream */ |
| if(pingPongCount <= 0){ |
| printf("count must be positive\n"); |
| return -1; |
| } |
| printf("Starting PING size:%d stream:%d\n",pingBufSize,pingStream); |
| doPingPong(fd); |
| return 0; |
| } |
| |
| |
| /* quit - quit the program */ |
| static int |
| cmd_quit(char *argv[], int argc) |
| { |
| dist_setDone(dist); |
| return 0; |
| } |
| |
| static int |
| cmd_printrftpstat(char *argv[], int argc) |
| { |
| printf("Stream 1 read %d\n",str1read); |
| printf("Stream 2 read %d\n",str2read); |
| str1read = str2read = 0; |
| return 0; |
| } |
| |
| /* rftp filename strm1 strm2 blocksz [n] - round-trip ftp */ |
| static int |
| cmd_rftp(char *argv[], int argc) |
| { |
| |
| char cbuf[255]; |
| char *file_in; |
| |
| if((pingPongCount>0) || bulkInProgress){ |
| printf("Sorry bulk or ping in progress, you must wait for completion" |
| "before sending\n"); |
| return -1; |
| } |
| if (argc < 4) { |
| printf("rftp needs at least 4 parameters, see help\n"); |
| return -1; |
| } |
| file_in = argv[0]; |
| rftp_in1 = fopen(file_in, "r"); |
| if(rftp_in1 == NULL){ |
| printf("Can't open file for strm1 err:%d for file '%s'\n", errno,file_in); |
| return -1; |
| } |
| |
| rftp_in2 = fopen(file_in, "r"); |
| if(rftp_in2 == NULL){ |
| printf("Can't open file for strm2 err:%d for file '%s'\n", errno,file_in); |
| return -1; |
| } |
| |
| rftp_strm1 = atoi(argv[1]); |
| rftp_strm2 = atoi(argv[2]); |
| rftp_bsz = atoi(argv[3]); |
| if(argc == 5) |
| rftp_rt = atoi(argv[4]); |
| else |
| rftp_rt = 0; /* unreliable for u-streams */ |
| sprintf(cbuf,"%s.strm%d.out",file_in,rftp_strm1); |
| rftp_out1 = fopen(cbuf, "w+"); |
| if(rftp_out1 == NULL){ |
| printf("Can't open file err:%d for file '%s'\n", errno, cbuf); |
| return -1; |
| } |
| sprintf(cbuf,"%s.strm%d.out",file_in,rftp_strm2); |
| rftp_out2 = fopen(cbuf, "w+"); |
| if(rftp_out2 == NULL){ |
| printf("Can't open file err:%d for file '%s'\n", errno, cbuf); |
| return -1; |
| } |
| /*=====*/ |
| printf("rftp started over streams %d and %d....\n", rftp_strm1, rftp_strm2); |
| rftp_ending1 = rftp_ending2 = 0; |
| str1Flow = str2Flow=0; |
| |
| sendRftpTransfer((void *)&adap->fd, NULL, 0); |
| |
| return 0; |
| } |
| |
| static int |
| cmd_closefd(char *argv[], int argc) |
| { |
| int fd, ret; |
| if(argc != 1){ |
| printf("Missing fd closefd must have a int arg\n"); |
| return(-1); |
| } |
| fd = strtol(argv[0], NULL, 0); |
| restore_SCTP_fd(adap); |
| if(fd == adap->fd){ |
| printf("Sorry can't close the main listening fd:%d\n",fd); |
| }else{ |
| ret = close(fd); |
| printf("close(fd:%d) returns %d errno:%d\n", |
| fd, ret, errno); |
| } |
| return(0); |
| } |
| |
| |
| static int |
| cmd_setfd(char *argv[], int argc) |
| { |
| int fd; |
| if(argc != 1){ |
| printf("Missing fd setfd must have a int arg\n"); |
| return(-1); |
| } |
| fd = strtol(argv[0], NULL, 0); |
| adap->fd = fd; |
| printf("Override fd to %d\n",fd); |
| return(0); |
| } |
| |
| static int |
| cmd_listen(char *argv[], int argc) |
| { |
| int backlog; |
| backlog = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(listen(adap->fd, backlog)){ |
| printf("Listen with backlog=%d fail's error %d\n", |
| backlog,errno); |
| } |
| #ifdef __APPLE__ |
| { |
| int opt = 0; |
| /* fix Apple listen() issue */ |
| setsockopt(adap->fd, IPPROTO_SCTP, SCTP_LISTEN_FIX, &opt, sizeof(opt)); |
| } |
| #endif |
| if(adap->model & SCTP_TCP_TYPE){ |
| if(backlog){ |
| printf("Turning on the listening flag\n"); |
| adap->model |= SCTP_TCP_IS_LISTENING; |
| }else{ |
| printf("Turning off the listening flag\n"); |
| adap->model &= ~SCTP_TCP_IS_LISTENING; |
| } |
| } |
| return(0); |
| } |
| |
| static int |
| cmd_restorefd(char *argv[], int argc) |
| { |
| restore_SCTP_fd(adap); |
| return(0); |
| } |
| |
| #ifndef SCTP_NO_TCP_MODEL |
| static int |
| cmd_peeloff(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| sctp_assoc_t assoc_id; |
| int newfd; |
| if(adap->model & SCTP_TCP_TYPE){ |
| printf("Peel off is not allowed on the TCP model, restart without -t\n"); |
| return(-1); |
| } |
| assoc_id = get_assoc_id(); |
| if(assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| printf("Peeling off fd:%d assoc_id:0x%xh\n", |
| adap->fd,(uint32_t)assoc_id); |
| newfd = sctp_peeloff(adap->fd, assoc_id); |
| if(newfd < 0){ |
| printf("Peel-off failed errno:%d\n",errno); |
| }else{ |
| printf("Peeled off fd is %d\n",newfd); |
| dist_addFd(adap->o,newfd,sctpFdInput,POLLIN,(void *)adap); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return(0); |
| } |
| #endif /* !SCTP_NO_TCP_MODEL */ |
| |
| static int cmd_getlocaladdrs(char *argv[], int argc) |
| { |
| struct sockaddr *raddr; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| int cnt,i; |
| sctp_assoc_t id; |
| if(argc > 0) { |
| id = strtoul(argv[0], NULL, 0); |
| } else { |
| id = get_assoc_id(); |
| } |
| raddr = NULL; |
| printf("Got asoc id 0x%x\n",(uint32_t)id); |
| cnt = sctp_getladdrs(adap->fd, id, (void *)&raddr); |
| printf("Cnt returned is %d\n",cnt); |
| if(raddr != NULL){ |
| if(id) |
| printf("Got %d addresses on my end of the association\n",cnt); |
| else |
| printf("Got %d addresses on my endpoint\n",cnt); |
| sa = raddr; |
| for(i=0;i<cnt;i++){ |
| #ifdef HAVE_SA_LEN |
| sa_len = sa->sa_len; |
| #else |
| if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in); |
| else if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in6); |
| #endif |
| printf("Address[%d] ",i); |
| SCTPPrintAnAddress(sa); |
| sa = (struct sockaddr *)((caddr_t)sa + sa_len); |
| if (sa_len == 0) |
| break; |
| } |
| sctp_freeladdrs(raddr); |
| } |
| return(0); |
| } |
| static int |
| cmd_getstatus(char *argv[], int argc) |
| { |
| struct sctp_status stat; |
| socklen_t sz; |
| |
| memset(&stat,0,sizeof(stat)); |
| stat.sstat_assoc_id = get_assoc_id(); |
| sz = sizeof(struct sctp_status); |
| if(stat.sstat_assoc_id == 0){ |
| printf("Can't get assoc id\n"); |
| return(-1); |
| } |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_STATUS, &stat, &sz) != 0) { |
| printf("Can't do GET_STATUS socket option! err:%d\n", errno); |
| return(-1); |
| } |
| printf("Association Id:0x%x\n",(uint32_t)stat.sstat_assoc_id); |
| printf(" State :0x%x\n",(uint32_t)stat.sstat_state); |
| printf(" unacked :0x%x\n",(uint32_t)stat.sstat_unackdata); |
| printf(" pending :0x%x\n",(uint32_t)stat.sstat_penddata); |
| printf(" in-strm :%d\n",(int)stat.sstat_instrms); |
| printf(" out-strm :%d\n",(int)stat.sstat_outstrms); |
| printf(" frag-point :%d\n",(int)stat.sstat_fragmentation_point); |
| printf(" Primary : "); |
| SCTPPrintAnAddress((struct sockaddr *)&stat.sstat_primary.spinfo_address); |
| printf("primary-state:%d \n",stat.sstat_primary.spinfo_state); |
| printf("primary-cwnd :%d \n",stat.sstat_primary.spinfo_cwnd); |
| printf("primary-rtt :%d \n",stat.sstat_primary.spinfo_srtt); |
| printf("primary-rto :%d \n",stat.sstat_primary.spinfo_rto); |
| printf("primary-mtu :%d \n",stat.sstat_primary.spinfo_mtu); |
| return(0); |
| } |
| |
| |
| |
| static int |
| cmd_getevents(char *argv[], int argc) |
| { |
| struct sctp_event_subscribe event; |
| socklen_t sz; |
| |
| sz = sizeof(event); |
| memset(&event,0,sizeof(event)); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) != 0) { |
| printf("Can't do SET_EVENTS socket option! err:%d\n", errno); |
| return(-1); |
| } |
| printf("DATA I/O events %s be received\n", |
| (event.sctp_data_io_event ? "Will" : "Will NOT")); |
| |
| printf("Association events %s be received\n", |
| (event.sctp_association_event ? "Will" : "Will NOT")); |
| |
| printf("Address events %s be received\n", |
| (event.sctp_address_event ? "Will" : "Will NOT")); |
| |
| printf("Send failure events %s be received\n", |
| (event.sctp_send_failure_event ? "Will" : "Will NOT")); |
| |
| printf("Peer error events %s be received\n", |
| (event.sctp_peer_error_event ? "Will" : "Will NOT")); |
| |
| printf("Shutdown events %s be received\n", |
| (event.sctp_shutdown_event ? "Will" : "Will NOT")); |
| |
| printf("PD-API events %s be received\n", |
| (event.sctp_partial_delivery_event ? "Will" : "Will NOT")); |
| |
| #if defined(__BSD_SCTP_STACK__) |
| printf("Adaption layer events %s be received\n", |
| (event.sctp_adaptation_layer_event ? "Will" : "Will NOT")); |
| #else |
| printf("Adaption layer events %s be received\n", |
| (event.sctp_adaption_layer_event ? "Will" : "Will NOT")); |
| #endif |
| |
| #if defined(__BSD_SCTP_STACK__) |
| printf("AUTHentication layer events %s be received\n", |
| (event.sctp_authentication_event ? "Will" : "Will NOT")); |
| |
| printf("Stream Reset events %s be received\n", |
| (event.sctp_stream_reset_event ? "Will" : "Will NOT")); |
| #endif |
| return(0); |
| } |
| |
| /* rwnd - get rwnds |
| */ |
| static int |
| cmd_rwnd(char *argv[], int argc) |
| { |
| struct sctp_assocparams sasoc; |
| sctp_assoc_t assoc_id; |
| socklen_t sz; |
| |
| assoc_id = get_assoc_id(); |
| if(assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| |
| printf("Setting on assoc id 0x%x\n",(uint32_t)assoc_id); |
| sasoc.sasoc_assoc_id = assoc_id; |
| sz = sizeof(sasoc); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ASSOCINFO, &sasoc, &sz) != 0) { |
| printf("get associnfo failed err:%d\n",errno); |
| }else{ |
| printf("My rwnd:%d peers rwnd:%d\n", |
| sasoc.sasoc_local_rwnd, |
| sasoc.sasoc_peer_rwnd); |
| } |
| return 0; |
| } |
| |
| |
| /* send string [n] - send string to a peer if a peer is set |
| */ |
| static int |
| cmd_send(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int ret, len, i, at; |
| char buffer[200]; |
| if (argc < 1) { |
| printf("send: expected at least 1 argument\n"); |
| return -1; |
| } |
| if (!(destinationSet && portSet)) { |
| printf("sorry first set a destination before sending\n"); |
| return -1; |
| } |
| if((pingPongCount>0) || bulkInProgress){ |
| printf("Sorry bulk or ping in progress, you must wait for completion" |
| "before sending\n"); |
| return -1; |
| } |
| at = len = 0; |
| for(i=0;i<argc;i++) { |
| if(argv[i][0] == '^') { |
| int val; |
| char *stop=NULL; |
| val= strtol(&argv[i][1], &stop , 0); |
| buffer[at] = val; |
| at++; |
| len++; |
| if(stop != NULL) { |
| int llen; |
| llen = strlen(stop); |
| memcpy(&buffer[at], stop, llen); |
| len += llen; |
| at += llen; |
| printf("Added %d bytes to end\n", llen); |
| } |
| buffer[at] = 0; |
| at++; |
| len++; |
| |
| } else { |
| len += strlen(argv[i]); |
| memcpy(&buffer[at], argv[i], strlen(argv[i])); |
| at += strlen(argv[i]); |
| } |
| } |
| ret = sctpSEND(fd, defStream, buffer, len, SCTP_getAddr(NULL), |
| sendOptions, payload, 0); |
| return 0; |
| } |
| |
| /* send asocid string [n] - send string to a peer if a peer is set |
| */ |
| static int |
| cmd_sendasoc(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int ret; |
| uint32_t aaa; |
| sctp_assoc_t asoc; |
| if (argc < 2) { |
| printf("send: expected at least 2 argument\n"); |
| return -1; |
| } |
| aaa = strtoul(argv[0], NULL, 0); |
| if(aaa == 0) { |
| printf("Sorry asocid 0 never valid\n"); |
| return -1; |
| } |
| asoc = (sctp_assoc_t)aaa; |
| ret = sctpsend_associd(fd, asoc, argv[1], strlen(argv[1]), sendOptions, payload); |
| printf("sctpsend_associd returned %d from the send\n",ret); |
| return 0; |
| } |
| |
| static int |
| cmd_sctpsendx(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_sndrcvinfo s_info; |
| int fd = adap->fd; |
| int port1; |
| uint16_t port; |
| int i, ret, addr_cnt=0; |
| char addr_buf[2048]; |
| char *at; |
| struct sockaddr_in *sin; |
| struct sockaddr_in6 *sin6; |
| struct sockaddr *sa; |
| |
| at = addr_buf; |
| if(argc < 3) { |
| printf("Error need at least 3 args, buffer port and addr('s)\n"); |
| return -1; |
| } |
| port1 = strtol(argv[1], NULL, 0); |
| port = htons((uint16_t)port1); |
| for (i=2; i<argc; i++) { |
| /* try v4 */ |
| sin = (struct sockaddr_in *)at; |
| ret = inet_pton(AF_INET, argv[i], &sin->sin_addr); |
| if(ret == 1) { |
| /* found it */ |
| addr_cnt++; |
| sin->sin_family = AF_INET; |
| sin->sin_len = sizeof(struct sockaddr_in); |
| sin->sin_port = port; |
| at += sizeof(struct sockaddr_in); |
| continue; |
| } |
| /* try v6 */ |
| sin6 = (struct sockaddr_in6 *)at; |
| ret = inet_pton(AF_INET6, argv[i], &sin6->sin6_addr); |
| if (ret == 1) { |
| /* found it */ |
| addr_cnt++; |
| sin6->sin6_family = AF_INET6; |
| sin6->sin6_len = sizeof(struct sockaddr_in6); |
| sin6->sin6_port = port; |
| at += sizeof(struct sockaddr_in6); |
| continue; |
| } |
| printf("I can't find a V4 or V6 address in %s - skipping\n", argv[i]); |
| } |
| if (addr_cnt == 0) { |
| printf ("no valid addresses found, sorry can't send anything\n"); |
| return -1; |
| } |
| sa = (struct sockaddr *)(addr_buf); |
| s_info.sinfo_stream = defStream; |
| s_info.sinfo_flags = sendOptions; |
| s_info.sinfo_ppid = payload; |
| s_info.sinfo_context = 0; |
| s_info.sinfo_timetolive = time_to_live; |
| s_info.sinfo_assoc_id = 0; |
| ret = sctp_sendx(fd, argv[0], strlen(argv[0]), sa, addr_cnt, &s_info,0); |
| printf("Return from sctp_sendx is %d\n",ret); |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| /* sendloop [num] - send test script loopback request of num size */ |
| static int |
| cmd_sendloop(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int x,ret; |
| |
| x = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(x <= 0){ |
| printf("num was 0? defaulting to 64\n"); |
| x = 64; |
| } |
| ret = sendLoopRequest(fd,x); |
| printf("Sent loop returned %d\n",ret); |
| return 0; |
| } |
| |
| |
| /* sendloopend [num] - send test script loopback request of num size and terminate |
| */ |
| static int |
| cmd_sendloopend(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int x; |
| |
| x = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(x <= 0){ |
| printf("num was 0? defaulting to 64\n"); |
| x = 64; |
| } |
| printf("Send loop request returns:%d\n",sendLoopRequest(fd,x)); |
| sctpTERMINATE(fd, SCTP_getAddr(NULL)); |
| printf("Sent loop and terminate queued\n"); |
| return 0; |
| } |
| |
| |
| /* sendreltlv num - send a rel-tlv of num bytes of data |
| */ |
| static int |
| cmd_sendreltlv(char *argv[], int argc) |
| { |
| /* |
| int fd = adap->fd; |
| int sz,ret; |
| char *xxx; |
| struct sctpParamDesc *TLVout; |
| struct SCTP_association *asoc; |
| struct sockaddr *add; |
| socklen_t add_len; |
| |
| if (argc != 1) { |
| printf("sendreltlv: expected 1 argument\n"); |
| return -1; |
| } |
| */ |
| /* This is actually a violation, we are calling a module that we |
| * really should not.. but this is so we can do |
| * a test by dumpping inqueue anything we want for a REL-REQ. |
| */ |
| /* |
| add = SCTP_getAddr(NULL); |
| |
| asoc = SCTPfindAssociation(fd, (struct sockaddr *)add, &sz); |
| if(asoc == NULL){ |
| printf("sorry can't find the association\n"); |
| return -1; |
| } |
| */ |
| /* sz = strtol(&readBuffer[11],NULL,0); */ |
| /* |
| sz = strtol(argv[0], NULL, 0); |
| if (sz <= 0) { |
| printf("sendreltlv: num must be positive\n"); |
| return -1; |
| } |
| sz += sizeof(struct sctpParamDesc); |
| xxx = calloc(1,sz); |
| if (xxx == NULL) { |
| printf("sendreltlv: sorry malloc failed.. queue fails\n"); |
| return -1; |
| } else { |
| u_short val,len,i; |
| char buf[10]; |
| |
| TLVout = (struct sctpParamDesc *)xxx; |
| printf("TLV value:"); |
| fflush(stdout); |
| fgets(buf,sizeof(buf),stdin); |
| val = (u_short)strtol(buf,NULL,0); |
| len = sz; |
| TLVout->paramType = htons(val); |
| TLVout->paramLength = htons(len); |
| for(i=0,len=sizeof(struct sctpParamDesc);len<sz;len++,i++){ |
| printf("Value for byte %d (0-255)",i); |
| fflush(stdout); |
| fgets(buf,sizeof(buf),stdin); |
| val = strtol(buf,NULL,0); |
| if(val > 255){ |
| printf("Error input:%d to big, replacing with 255\n",val); |
| xxx[len] = 255; |
| }else{ |
| xxx[len] = val; |
| } |
| } |
| printf("Delayed send (y, n, e, def=n):"); |
| fflush(stdout); |
| fgets(buf,sizeof(buf),stdin); |
| if(buf[0] == 'y'){ |
| ret = SCTPqueueARelReq(fd,asoc,TLVout,1); |
| }else{ |
| struct sctpParamDesc *TLVout2; |
| TLVout2 = NULL; |
| if(buf[0] == 'e'){ |
| xxx = calloc(1,sz); |
| if(xxx != NULL){ |
| memcpy(xxx,(char *)TLVout,sz); |
| } |
| TLVout2 = (struct sctpParamDesc *)xxx; |
| } |
| ret = SCTPqueueARelReq(fd,asoc,TLVout,0); |
| */ |
| /* echo out a copy again to queue */ |
| /* |
| if(TLVout2 != NULL){ |
| ret = SCTPqueueARelReq(fd,asoc,TLVout2,0); |
| } |
| } |
| printf("Queue of REL-REQ returns %d\n",ret); |
| if(ret < 0){ |
| free(xxx); |
| } |
| } |
| */ |
| return 0; |
| } |
| |
| |
| /* setbulkmode ascii/binary - set bulk transfer mode |
| */ |
| static int |
| cmd_setbulkmode(char *argv[], int argc) |
| { |
| if (argc != 1) { |
| printf("setbulkmode: expected 1 argument\n"); |
| return -1; |
| } |
| switch (argv[0][0]) { |
| case 'a': |
| bulkPingMode = 0; |
| printf("bulk/ping transfer set to ascii mode\n"); |
| break; |
| case 'b': |
| bulkPingMode = 1; |
| printf("bulk/ping transfer set to binary mode\n"); |
| break; |
| default: |
| printf("setbulkmode: expected ascii/binary\n"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| |
| /* setdefcookielife num - set default cookie life |
| */ |
| static int |
| cmd_setdefcookielife(char *argv[], int argc) |
| { |
| int num; |
| struct sctp_assocparams sasoc; |
| |
| if (argc < 1) { |
| printf("defretrys: expected 1 or 2 argument\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(num == 0){ |
| printf("Sorry argument 1 must be a postive number\n"); |
| return -1; |
| } |
| memset(&sasoc,0,sizeof(sasoc)); |
| /* Set in the value */ |
| sasoc.sasoc_cookie_life = num; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ASSOCINFO, &sasoc, sizeof(sasoc)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| return 0; |
| } |
| |
| |
| /* setdefstream num - set the default stream to |
| */ |
| static int |
| cmd_setdefstream(char *argv[], int argc) |
| { |
| if (argc != 1) { |
| printf("setdefstream: expected 1 argument\n"); |
| return -1; |
| } |
| /* XXX add validity check on stream number */ |
| defStream = strtol(argv[0], NULL, 0); |
| return 0; |
| } |
| |
| |
| /* seterr num - set the association send error thresh */ |
| static int |
| cmd_seterr(char *argv[], int argc) |
| { |
| struct sctp_assocparams sasoc; |
| struct sctp_paddrparams sp; |
| struct sockaddr *sa; |
| socklen_t sa_len; |
| socklen_t siz; |
| int num; |
| |
| if (argc < 1) { |
| printf("defretrys: expected 1 argument\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(num == 0){ |
| printf("Sorry argument 1 must be a postive number\n"); |
| return -1; |
| } |
| memset(&sasoc,0,sizeof(sasoc)); |
| /* Set in the value */ |
| sasoc.sasoc_asocmaxrxt = num; |
| /* Get the association id so I can set this only on the assoc. */ |
| |
| siz = sizeof(sp); |
| sa = SCTP_getAddr(&sa_len); |
| memset(&sp,0,sizeof(sp)); |
| memcpy((caddr_t)&sp.spp_address, sa, sa_len); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0) { |
| printf("Failed to get assoc id with HB info err:%d\n",errno); |
| return 0; |
| } |
| printf("Setting on assoc id 0x%x\n",(uint32_t)sp.spp_assoc_id); |
| sasoc.sasoc_assoc_id = sp.spp_assoc_id; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_ASSOCINFO, &sasoc, sizeof(sasoc)) != 0) { |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| }else{ |
| printf("Ka-pla\n"); |
| } |
| return 0; |
| } |
| |
| |
| /* sethost host|X.Y.Z.A - set the destination host IP address |
| */ |
| static int |
| cmd_sethost(char *argv[], int argc) |
| { |
| struct in_addr in; |
| |
| if (inet_pton(AF_INET, argv[0], &in)) { |
| SCTP_setIPaddr(in.s_addr); |
| }else{ |
| printf("can't set IPv4: incorrect address format\n"); |
| return -1; |
| } |
| destinationSet++; |
| printf("To Set "); |
| SCTPPrintAnAddress(SCTP_getAddr(NULL)); |
| return 0; |
| } |
| |
| |
| /* sethost6 host|xx:xx:xx...:xx - set the destination host IPv6 address |
| */ |
| static int |
| cmd_sethost6(char *argv[], int argc) |
| { |
| struct in6_addr in6; |
| |
| if(inet_pton(AF_INET6, argv[0], &in6)){ |
| SCTP_setIPaddr6((u_char *)&in6); |
| }else{ |
| printf("can't set IPv6: incorrect address format\n"); |
| return -1; |
| } |
| destinationSet++; |
| printf("To Set "); |
| SCTPPrintAnAddress(SCTP_getAddr(NULL)); |
| return 0; |
| } |
| |
| |
| /* setneterr net val - set the association network error thresh */ |
| static int |
| cmd_setneterr(char *argv[], int argc) |
| { |
| struct sockaddr *sa, *addrs; |
| socklen_t sa_len; |
| struct sctp_paddrparams paddr; |
| sctp_assoc_t assoc_id; |
| int numnets; |
| int i,net,val; |
| |
| if (argc != 2) { |
| printf("setneterr: expected 2 arguments\n"); |
| return -1; |
| } |
| net = strtol(argv[0], NULL, 0); |
| val = strtol(argv[1], NULL, 0); |
| if (val < 1) { |
| printf("setneterr: val out of range\n"); |
| return -1; |
| } |
| /* Got to get the assoc id */ |
| assoc_id = get_assoc_id(); |
| if(assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| |
| #ifdef SOLARIS |
| numnets = sctp_getpaddrs(adap->fd, assoc_id, (void *)&addrs); |
| #else |
| numnets = sctp_getpaddrs(adap->fd, assoc_id, &addrs); |
| #endif /* SOLARIS */ |
| if (numnets < 0) { |
| printf("Can't get the peer addresses\n"); |
| return -1; |
| } |
| if (net <= 0 || net >= numnets) { |
| printf("setneterr: net out of range\n"); |
| free(addrs); |
| return -1; |
| } |
| printf("Setting net:%d failure threshold to %d\n", net,val); |
| |
| /* find the desired net */ |
| sa = addrs; |
| for(i=0; i<net; i++){ |
| #ifdef HAVE_SA_LEN |
| sa_len = sa->sa_len; |
| #else |
| if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in); |
| else if (sa->sa_family == AF_INET6) |
| sa_len = sizeof(struct sockaddr_in6); |
| #endif |
| sa = (struct sockaddr *)((caddr_t)sa + sa_len); |
| } |
| |
| memset(&paddr,0,sizeof(paddr)); |
| SCTPPrintAnAddress(sa); |
| paddr.spp_assoc_id = assoc_id; |
| memcpy(&paddr.spp_address, sa, sizeof(paddr.spp_address)); |
| paddr.spp_pathmaxrxt = val; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PEER_ADDR_PARAMS, &paddr, sizeof(paddr)) != 0) { |
| sctp_freepaddrs(addrs); |
| printf("Failed to set option %d\n",errno); |
| return 0; |
| } |
| sctp_freepaddrs(addrs); |
| return 0; |
| } |
| |
| static int |
| parse_send_opt(char *p) |
| { |
| printf("Parsing option '%s'\n",p); |
| if(strcmp(p,"prsctp") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return(SCTP_PR_SCTP_TTL); |
| }else if(strcmp(p,"rxt") == 0) { |
| return (SCTP_PR_SCTP_RTX); |
| }else if(strcmp(p,"bufbnd") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return(SCTP_PR_SCTP_BUF); |
| }else if(strcmp(p,"unord") == 0){ |
| return(SCTP_UNORDERED); |
| }else if(strcmp(p,"over") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return(SCTP_ADDR_OVER); |
| }else if(strcmp(p,"abort") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return (SCTP_ABORT); |
| }else if(strcmp(p,"eof") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return (SCTP_EOF); |
| }else if(strcmp(p,"eeom") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return (SCTP_EOR); |
| }else if(strcmp(p,"sendall") == 0){ |
| #if !defined(__BSD_SCTP_STACK__) |
| printf("%s option: Not supported on this OS\n", p); |
| #endif |
| return (SCTP_SENDALL); |
| }else if(strcmp(p,"none") == 0){ |
| return(0); |
| }else{ |
| printf("Sorry option %s not known, value must be:\n eof|abort|eeom|prsctp|bufbnd|unord|over|none|rxt|sendall\n",p); |
| } |
| return(0); |
| } |
| /* setopts val - set options to specified value |
| */ |
| static int |
| cmd_setopts(char *argv[], int argc) |
| { |
| int len, i; |
| char *p; |
| if (argc != 1) { |
| printf("setopts: expected 1 argument\n"); |
| return -1; |
| } |
| sendOptions = 0; |
| len = strlen(argv[0]); |
| p = argv[0]; |
| for (i = 0; i < len; i++) { |
| if (argv[0][i] == '|') { |
| argv[0][i] = 0; |
| sendOptions |= parse_send_opt(p); |
| p = &argv[0][(i + 1)]; |
| } |
| } |
| sendOptions |= parse_send_opt(p); |
| printf("Send options now set to 0x%x\n", sendOptions); |
| return 0; |
| } |
| |
| |
| /* setpay payloadt - set the payload type |
| */ |
| static int |
| cmd_setpay(char *argv[], int argc) |
| { |
| if (argc != 1) { |
| printf("setpay: expected 1 argument\n"); |
| return -1; |
| } |
| /* XXX add input validation */ |
| payload = strtol(argv[0], NULL, 0); |
| printf("payloadtype set to %d\n",payload); |
| return 0; |
| } |
| |
| |
| /* setport port - set the destination SCTP port number |
| */ |
| static int |
| cmd_setport(char *argv[], int argc) |
| { |
| unsigned short pt; |
| |
| pt = (unsigned short)strtol(argv[0],NULL,0); |
| SCTP_setport(htons(pt)); |
| printf("Address set to "); |
| SCTPPrintAnAddress(SCTP_getAddr(NULL)); |
| portSet++; |
| return 0; |
| } |
| |
| static int cmd_setautoasconf(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| int num; |
| if(argc < 1){ |
| printf("setautoasconf needs numric value 0/1\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_AUTO_ASCONF,&num,sizeof(num)) != 0) { |
| printf("Can't set auto-asconf flag error:%d\n",errno); |
| return -1; |
| } |
| printf("auto asconf is now %s\n", ((num) ? "on" : "off")); |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| static int cmd_getautoasconf(char *argv[], int argc) |
| { |
| #if defined(__BSD_SCTP_STACK__) |
| int num; |
| socklen_t optlen; |
| |
| optlen = sizeof(num); |
| if(getsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_AUTO_ASCONF,&num,&optlen) != 0) { |
| printf("Can't get auto-asconf flag error:%d\n",errno); |
| return -1; |
| } |
| printf("auto asconf is now %s\n", ((num) ? "on" : "off")); |
| return 0; |
| #else |
| printf("Not supported on this OS\n"); |
| return (0); |
| #endif |
| } |
| |
| /* setprimary - set current ip address to the primary address */ |
| static int |
| cmd_setprimary(char *argv[], int argc) |
| { |
| struct sockaddr *sa, *addrs; |
| socklen_t sa_len = 0; |
| #if defined(linux) |
| struct sctp_prim prim; |
| #else |
| struct sctp_setprim prim; |
| #endif |
| int numnets,num,i; |
| sctp_assoc_t assoc_id; |
| int siz; |
| |
| if(argc < 1){ |
| printf("setprimary needs numeric index of new primary\n"); |
| return -1; |
| } |
| num = argv[0] != NULL ? strtol(argv[0], NULL, 0) : 0; |
| assoc_id = get_assoc_id(); |
| if(assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| |
| #ifdef SOLARIS |
| numnets = sctp_getpaddrs(adap->fd, assoc_id, (void *)&addrs); |
| #else |
| numnets = sctp_getpaddrs(adap->fd, assoc_id, &addrs); |
| #endif /* SOLARIS */ |
| if (numnets < 0) { |
| printf("Can't get the peer addresses\n"); |
| return -1; |
| } |
| if((num >= numnets) || (num < 0)){ |
| printf("Invalid address number range is 0 to %d\n",(numnets-1)); |
| sctp_freepaddrs(addrs); |
| return -1; |
| } |
| sa = addrs; |
| for(i=0;i<numnets;i++){ |
| #ifdef HAVE_SA_LEN |
| sa_len = sa->sa_len; |
| #else |
| if (sa->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in); |
| else if (sa->sa_family == AF_INET6) |
| sa_len = sizeof(struct sockaddr_in6); |
| #endif |
| if(i == num){ |
| memcpy(&prim.ssp_addr, sa, sa_len); |
| break; |
| } |
| sa = (struct sockaddr *)((caddr_t)sa + sa_len); |
| } |
| prim.ssp_assoc_id = assoc_id; |
| sctp_freepaddrs(addrs); |
| siz = sizeof(prim); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_PRIMARY_ADDR,&prim,sizeof(prim)) != 0) { |
| printf("Can't set primary address error:%d\n",errno); |
| return -1; |
| } |
| printf("Primary address is "); |
| SCTPPrintAnAddress((struct sockaddr *)&prim.ssp_addr); |
| return 0; |
| } |
| |
| |
| /* setremprimary address - set remote's primary address */ |
| static int |
| cmd_setremprimary(char *argv[], int argc) |
| { |
| char *address; |
| struct addrinfo hints, *res; |
| socklen_t sa_len = 0; |
| struct sctp_setpeerprim sspp; |
| int ret; |
| |
| if (argc < 1) { |
| printf("setremprimary: expected 1 argument\n"); |
| return -1; |
| } |
| address = argv[0]; |
| |
| bzero(&hints, sizeof(hints)); |
| hints.ai_flags = AI_NUMERICHOST; /* disable name resolution */ |
| ret = getaddrinfo(address, NULL, &hints, &res); |
| if(ret != 0){ |
| printf("setremprimary: getaddrinfo: %s\n", gai_strerror(ret)); |
| return -1; |
| } |
| printf("setremprimary: setting remote primary %s\n", address); |
| memset(&sspp,0,sizeof(sspp)); |
| if(argc > 1) { |
| sspp.sspp_assoc_id = 0; |
| printf("Giving 0 lenght to set peer primary\n"); |
| } else { |
| sspp.sspp_assoc_id = get_assoc_id(); |
| if(sspp.sspp_assoc_id == 0){ |
| printf("Can't find association\n"); |
| return(-1); |
| } |
| } |
| #ifdef HAVE_SA_LEN |
| sa_len = res->ai_addr->sa_len; |
| #else |
| if (res->ai_addr->sa_family == AF_INET) |
| sa_len = sizeof(struct sockaddr_in); |
| else if (res->ai_addr->sa_family == AF_INET6) |
| sa_len = sizeof(struct sockaddr_in6); |
| #endif |
| memcpy(&sspp.sspp_addr,res->ai_addr,sa_len); |
| if(setsockopt(adap->fd,IPPROTO_SCTP, |
| SCTP_SET_PEER_PRIMARY_ADDR,&sspp,sizeof(sspp)) != 0) { |
| printf("Can't set peer primary address error:%d\n",errno); |
| return -1; |
| }else{ |
| printf("Requested Peer Primary address is "); |
| SCTPPrintAnAddress((struct sockaddr *)&sspp.sspp_addr); |
| } |
| freeaddrinfo(res); |
| return(0); |
| } |
| |
| |
| /* setscope num - Set the IPv6 scope id */ |
| static int |
| cmd_setscope(char *argv[], int argc) |
| { |
| uint32_t scop; |
| |
| if (argc != 1) { |
| printf("setscope: expected 1 argument\n"); |
| return -1; |
| } |
| scop = (uint32_t)strtoul(argv[0],NULL,0); |
| /* XXX add input validation */ |
| SCTP_setIPv6scope(scop); |
| printf("Set scope id of %d address\n",scop); |
| SCTPPrintAnAddress(SCTP_getAddr(NULL)); |
| return 0; |
| } |
| |
| |
| /* setstreams numpreopenstrms - set the number of streams I request |
| */ |
| static int |
| cmd_setstreams(char *argv[], int argc) |
| { |
| printf("Obsolete, use 'setinitparam'\n"); |
| return 0; |
| } |
| |
| |
| /* startmultping - start the defined ping pong contexts |
| */ |
| static int |
| cmd_startmultping(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| int i; |
| time_t x; |
| struct tm *timeptr; |
| |
| if(pingPongsDefined <= 0){ |
| printf("No ping pong contexts defined\n"); |
| }else{ |
| /* prepare ping buffer */ |
| pingBufSize = 500; |
| strncpy(pingBuffer,"ping", 4); |
| for(i = 4;i<pingBufSize;i++) { |
| pingBuffer[i] = 'A' + (i%26); |
| } |
| for(i = 0;i< MAX_PING_PONG_CONTEXTS;i++){ |
| if((pingPongTable[i].stream != -1) && |
| (pingPongTable[i].started == 0)){ |
| sctpSEND(fd,pingPongTable[i].stream,pingBuffer,pingBufSize, |
| SCTP_getAddr(NULL),sendOptions,payload,0); |
| pingPongTable[i].started = 1; |
| x = time(NULL); |
| timeptr = localtime(&x); |
| printf("Starting on stream %d at %s",pingPongTable[i].stream, |
| asctime(timeptr)); |
| } |
| } |
| } |
| return 0; |
| } |
| |
| |
| /* tella host - confess what translateIPAddress returns |
| * XXX IPv4 only |
| */ |
| static int |
| cmd_tella(char *argv[], int argc) |
| { |
| u_long x; |
| |
| if (argc != 1) { |
| printf("tella: expected 1 argument\n"); |
| return -1; |
| } |
| x = ntohl(translateIPAddress(argv[0])); |
| printf("Address is %d.%d.%d.%d\n", |
| (int)((x>>24) & 0x000000ff), |
| (int)((x>>16) & 0x000000ff), |
| (int)((x>>8) & 0x000000ff), |
| (int)(x & 0x000000ff) |
| ); |
| return 0; |
| } |
| |
| |
| /* term - terminate the set destination association (graceful shutdown) |
| */ |
| static int |
| cmd_term(char *argv[], int argc) |
| { |
| int fd = adap->fd; |
| |
| if(adap->model & SCTP_TCP_TYPE){ |
| if(adap->model & SCTP_TCP_IS_LISTENING){ |
| restore_SCTP_fd(adap); |
| if(fd == adap->fd) |
| printf("Sorry can't shutdown the listening socket\n"); |
| else |
| shutdown(fd,SHUT_RDWR); |
| }else{ |
| shutdown(fd,SHUT_RDWR); |
| } |
| }else{ |
| sctpTERMINATE(fd,SCTP_getAddr(NULL)); |
| } |
| return 0; |
| } |
| |
| /* whereto - tell where the default sends |
| */ |
| |
| static int |
| cmd_whereto(char *argv[], int argc) |
| { |
| printf("Currently sending to:"); |
| SCTPPrintAnAddress(SCTP_getAddr(NULL)); |
| return 0; |
| } |
| |
| /* |
| * authentication support |
| */ |
| static int cmd_addauth(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_authchunk auth; |
| int count; |
| |
| if (argc < 1) { |
| printf("Expected: addauth <chunk_type> [<chunk_type> ...]\n"); |
| return (-1); |
| } |
| bzero(&auth, sizeof(auth)); |
| for (count=0; count < argc; count++) { |
| auth.sauth_chunk = (uint8_t)strtoul(argv[count], NULL, 0); |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, |
| &auth, sizeof(auth)) != 0) { |
| printf("Can't add chunk %u, errno %d\n", auth.sauth_chunk, errno); |
| return (-1); |
| } else { |
| printf("Added chunk %u to required list\n", auth.sauth_chunk); |
| } |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_addkey(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| char optval[512]; |
| struct sctp_authkey *key; |
| int keylen; |
| |
| if ((argc < 2) || (argc > 3)) { |
| printf("Expected: addkey <key_id> <key_text> [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(optval, sizeof(optval)); |
| key = (struct sctp_authkey *)optval; |
| key->sca_keynumber = (uint16_t)strtoul(argv[0], NULL, 0); |
| keylen = strlen(argv[1]); |
| strncpy((char *)key->sca_key, argv[1], keylen); |
| /* use the optional assoc id, if given */ |
| if (argc == 3) |
| key->sca_assoc_id = (uint32_t)strtoul(argv[2], NULL, 0); |
| else |
| key->sca_assoc_id = get_assoc_id(); |
| |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_KEY, optval, |
| sizeof(*key) + keylen) != 0) { |
| printf("Can't add key id %u, errno %d\n", key->sca_keynumber, errno); |
| return (-1); |
| } else { |
| printf("Added key id %u: %s\n", key->sca_keynumber, argv[1]); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_addnullkey(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| char optval[512]; |
| struct sctp_authkey *key; |
| int keylen; |
| |
| if ((argc < 1) || (argc > 2)) { |
| printf("Expected: addnullkey <key_id> [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(optval, sizeof(optval)); |
| key = (struct sctp_authkey *)optval; |
| key->sca_keynumber = (uint16_t)strtoul(argv[0], NULL, 0); |
| keylen = 0; |
| /* use the optional assoc id, if given */ |
| if (argc == 2) |
| key->sca_assoc_id = (uint32_t)strtoul(argv[1], NULL, 0); |
| else |
| key->sca_assoc_id = get_assoc_id(); |
| |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_KEY, optval, |
| sizeof(*key) + keylen) != 0) { |
| printf("Can't add null key id %u, errno %d\n", key->sca_keynumber, |
| errno); |
| return (-1); |
| } else { |
| printf("Added null key id %u\n", key->sca_keynumber); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_deactivatekey(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_authkeyid key; |
| |
| if ((argc < 1) || (argc > 2)) { |
| printf("Expected: deactivatekey <key_id> [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(&key, sizeof(key)); |
| key.scact_keynumber = (uint16_t)strtoul(argv[0], NULL, 0); |
| /* use the optional assoc id, if given */ |
| if (argc == 2) |
| key.scact_assoc_id = (uint32_t)strtoul(argv[1], NULL, 0); |
| else |
| key.scact_assoc_id = get_assoc_id(); |
| |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY, &key, |
| sizeof(key)) != 0) { |
| printf("Can't deactivate key id %u, errno %d\n", key.scact_keynumber, |
| errno); |
| return (-1); |
| } else { |
| printf("Deactivated key id %u\n", key.scact_keynumber); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_deletekey(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_authkeyid key; |
| |
| if ((argc < 1) || (argc > 2)) { |
| printf("Expected: deletekey <key_id> [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(&key, sizeof(key)); |
| key.scact_keynumber = (uint16_t)strtoul(argv[0], NULL, 0); |
| /* use the optional assoc id, if given */ |
| if (argc == 2) |
| key.scact_assoc_id = (uint32_t)strtoul(argv[1], NULL, 0); |
| else |
| key.scact_assoc_id = get_assoc_id(); |
| |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, &key, |
| sizeof(key)) != 0) { |
| printf("Can't delete key id %u, errno %d\n", key.scact_keynumber, |
| errno); |
| return (-1); |
| } else { |
| printf("Deleted key id %u\n", key.scact_keynumber); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_setactivekey(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_authkeyid key; |
| |
| if ((argc < 1) || (argc > 2)) { |
| printf("Expected: setactivekey <key_id> [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(&key, sizeof(key)); |
| key.scact_keynumber = (uint16_t)strtoul(argv[0], NULL, 0); |
| /* use the optional assoc id, if given */ |
| if (argc == 2) |
| key.scact_assoc_id = (uint32_t)strtoul(argv[1], NULL, 0); |
| else |
| key.scact_assoc_id = get_assoc_id(); |
| |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &key, |
| sizeof(key)) != 0) { |
| printf("Can't set key id %u active, errno %d\n", key.scact_keynumber, |
| errno); |
| return (-1); |
| } else { |
| printf("Set key id %u as active send key\n", key.scact_keynumber); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_getactivekey(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| struct sctp_authkeyid key; |
| socklen_t optlen; |
| |
| if (argc > 1) { |
| printf("Expected: getactivekey [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(&key, sizeof(key)); |
| /* use the optional assoc id, if given */ |
| if (argc == 1) |
| key.scact_assoc_id = (uint32_t)strtoul(argv[0], NULL, 0); |
| else |
| key.scact_assoc_id = get_assoc_id(); |
| |
| optlen = sizeof(key); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &key, |
| &optlen) != 0) { |
| printf("Can't get active key, errno %d\n", errno); |
| return (-1); |
| } else { |
| printf("Key id %u is active send key\n", key.scact_keynumber); |
| } |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_sethmac(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| char optval[512]; |
| struct sctp_hmacalgo *hmacs; |
| socklen_t optlen; |
| int num_hmacs, i; |
| |
| if (argc < 1) { |
| printf("Expected: sethmac <list of hmac ids>]\n"); |
| return (-1); |
| } |
| hmacs = (struct sctp_hmacalgo *)optval; |
| optlen = sizeof(optval); |
| num_hmacs = argc; |
| for (i=0; i < num_hmacs; i++) |
| hmacs->shmac_idents[i] = (uint32_t)strtoul(argv[i], NULL, 0); |
| optlen = sizeof(*hmacs) + (num_hmacs * sizeof(hmacs->shmac_idents[0])); |
| if (setsockopt(adap->fd, IPPROTO_SCTP, SCTP_HMAC_IDENT, optval, |
| optlen) != 0) { |
| printf("Can't set hmacs, errno:%d\n", errno); |
| return (-1); |
| } |
| printf("%u HMAC id's were set\n", num_hmacs); |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_gethmac(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| char optval[512]; |
| struct sctp_hmacalgo *hmacs; |
| socklen_t optlen; |
| int num_hmacs, i; |
| |
| hmacs = (struct sctp_hmacalgo *)optval; |
| optlen = sizeof(optval); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_HMAC_IDENT, optval, |
| &optlen) != 0) { |
| printf("Can't get hmacs, errno:%d\n", errno); |
| return (-1); |
| } |
| num_hmacs = (optlen - sizeof(*hmacs)) / sizeof(hmacs->shmac_idents[0]); |
| printf("%u HMAC id's\n", num_hmacs); |
| for (i=0; i < num_hmacs; i++) |
| printf(" HMAC id: %u (0x%02x)\n", hmacs->shmac_idents[i], |
| hmacs->shmac_idents[i]); |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_getlocalauth(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| char optval[512]; |
| struct sctp_authchunks *chunks; |
| socklen_t optlen; |
| int size, i; |
| |
| if (argc > 1) { |
| printf("Expected: getlocalauth [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(optval, sizeof(optval)); |
| chunks = (struct sctp_authchunks *)optval; |
| /* use the optional assoc id, if given */ |
| if (argc == 1) |
| chunks->gauth_assoc_id = (uint32_t)strtoul(argv[0], NULL, 0); |
| else |
| chunks->gauth_assoc_id = get_assoc_id(); |
| optlen = sizeof(optval); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, |
| optval, &optlen) != 0) { |
| printf("Can't get local auth chunks, errno:%d\n",errno); |
| return (-1); |
| } |
| size = optlen - sizeof(*chunks); |
| printf("%u Local chunks requiring AUTH\n", size); |
| for (i=0; i < size; i++) |
| printf(" chunk type: %u (0x%02x)\n", chunks->gauth_chunks[i], |
| chunks->gauth_chunks[i]); |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |
| |
| static int cmd_getpeerauth(char *argv[], int argc) { |
| #if defined(__BSD_SCTP_STACK__) |
| char optval[512]; |
| struct sctp_authchunks *chunks; |
| socklen_t optlen; |
| int size, i; |
| |
| if (argc > 1) { |
| printf("Expected: getlocalauth [<optional assoc id>]\n"); |
| return (-1); |
| } |
| bzero(optval, sizeof(optval)); |
| chunks = (struct sctp_authchunks *)optval; |
| /* use the optional assoc id, if given */ |
| if (argc == 1) |
| chunks->gauth_assoc_id = (uint32_t)strtoul(argv[0], NULL, 0); |
| else |
| chunks->gauth_assoc_id = get_assoc_id(); |
| optlen = sizeof(optval); |
| if (getsockopt(adap->fd, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, |
| optval, &optlen) != 0) { |
| printf("Can't get peer auth chunks, errno:%d\n",errno); |
| return (-1); |
| } |
| size = optlen - sizeof(*chunks); |
| printf("%u Peer chunks requiring AUTH\n", size); |
| for (i=0; i < size; i++) |
| printf(" chunk type: %u (0x%02x)\n", chunks->gauth_chunks[i], |
| chunks->gauth_chunks[i]); |
| #else |
| printf("Not supported on this OS\n"); |
| #endif |
| return (0); |
| } |