Created
May 4, 2021 11:50
-
-
Save Dyrcona/b60f239f382ee74c063d9138a2d815b2 to your computer and use it in GitHub Desktop.
A C program to check if a 3M SIP2 Protocol server is alive by sending the SC Status message.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright © 2021 Jason J.A. Stephenson <[email protected]> | |
* | |
* This program is free software: you can redistribute it and/or | |
* modify it under the terms of the GNU General Public License as | |
* published by the Free Software Foundation, either version 2 of the | |
* License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, but | |
* WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see | |
* <http://www.gnu.org/licenses/>. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> | |
/* | |
* This program is meant to be used as a health check for 3M SIP2 | |
* Protocol servers with ldirectord or haproxy. It is specifically | |
* written to be used with the F/OSS Evergreen ILS SIPServer program. | |
* It *may* work with other SIP server implementations, but none have | |
* been tested. | |
* | |
* It sends a 3M SIP2 Protocol SC Status message (99) to the SIP | |
* server without logging in. The SIP server, therefore, must allow | |
* the SC Status message before login. This is accomplished for the | |
* Evergreen ILS SIPServer by adding allow_sc_status_then_login="true" | |
* to the configuration for the RAW transport service in the | |
* oils_sip.xml configuration file. | |
* | |
* NOTE: This program does NOT send the sequence nor checksum fields, | |
* as checksums are redundant over TCP connections. If your SIP | |
* server requires checksums, then you will have to add the code to | |
* generate the sequence and checksum and add them to the message. | |
* | |
* The program returns 0, which both ldirectord and haproxy accept as | |
* OK, if it can connect to the SIP server, send the SC Status message | |
* and receives the ACS Status message (98) from the server | |
* indicating the on-line status of the SIP server is OK, i.e. the | |
* message begins 98Y. If the connection fails, the SIP server | |
* doesn't respond or responds with a different message, then the | |
* program returns 1, which both ldirectord and haproxy interpret as | |
* failure. The load balancer/proxy will then follow its | |
* configuration for what to do with a failed server. | |
* | |
* The two load balancers both pass 4 arguments to the program, but | |
* the program only uses the 3rd and 4th arguments which correspond to | |
* the SIP server's real IP address and real port, respectively. | |
* These are used to connect to the SIP server and send the SC Status | |
* message. | |
* | |
* To install the program, you would first compile it (see below), | |
* then copy it to an accessible location on your load balancer or | |
* proxy servers (/usr/local/bin is common or a chroot is setup for | |
* haproxy), and adjust your load balancer or proxy configuration as | |
* appropriate to use the program to check the status of your SIP | |
* servers (see your software's documentation). | |
* | |
* compile (on Debian or Ubuntu GNU/Linux): | |
* cc -O2 -o sip2status sip2status.c | |
*/ | |
int main(int argc, char *argv[]) { | |
int rv = 1; // Assume failure. | |
/* ldirectord/haproxy give us four or five arguments. We only care about 3 and 4. */ | |
char *remoteIP = argv[3]; | |
char *remotePort = argv[4]; | |
char *message = "9902552.00\r"; | |
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
struct sockaddr_in remoteAddr; | |
memset(&remoteAddr, 0, sizeof(struct sockaddr_in)); | |
remoteAddr.sin_family = AF_INET; | |
remoteAddr.sin_port = htons((uint16_t) atoi(remotePort)); | |
inet_pton(AF_INET, remoteIP, &remoteAddr.sin_addr); | |
if (connect(sockfd, (struct sockaddr *)&remoteAddr, sizeof(remoteAddr)) != -1) { | |
if (write(sockfd, (void *)message, strlen(message)) != -1) { | |
char response[512]; // Certainly big enough... | |
memset(response, 0, 512); | |
if (read(sockfd, (void *)response, 511) != -1) { | |
if (strncmp(response, "98Y", 3) == 0) | |
rv = 0; // Success! | |
} | |
} | |
close(sockfd); | |
} | |
return rv; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment