diff options
author | horchi <vdr@jwendel.de> | 2020-08-21 16:36:52 +0200 |
---|---|---|
committer | horchi <vdr@jwendel.de> | 2020-08-21 16:36:52 +0200 |
commit | 740602403557156183e5fdedca7f0e9b9618897f (patch) | |
tree | 682debe540be0d18547c47f4ff09ddd1b5673d75 /common.c | |
parent | 6853f2b6327e468efb77fa989dfa6080c257cf6c (diff) | |
download | vdr-plugin-seduatmo-740602403557156183e5fdedca7f0e9b9618897f.tar.gz vdr-plugin-seduatmo-740602403557156183e5fdedca7f0e9b9618897f.tar.bz2 |
2020-08-21: Version 0.0.10\n - added: Auto powerof by TV state (option -t <ip\ndns>)\n\n0.0.10
Diffstat (limited to 'common.c')
-rw-r--r-- | common.c | 181 |
1 files changed, 174 insertions, 7 deletions
@@ -6,6 +6,11 @@ */ #include <sys/time.h> +#include <sys/param.h> +#include <netinet/in_systm.h> +#include <netinet/ip_icmp.h> +#include <netdb.h> + #include <stdarg.h> #include <string.h> #include <syslog.h> @@ -31,12 +36,12 @@ void tell(int eloquence, const char* format, ...) va_list ap; cMutexLock lock(&logMutex); - + va_start(ap, format); snprintf(t, sizeBuffer, "SEDUATMO: "); vsnprintf(t+strlen(t), sizeBuffer-strlen(t), format, ap); - + syslog(LOG_ERR, "%s", t); va_end(ap); @@ -53,12 +58,12 @@ int error(const char* format, ...) va_list ap; cMutexLock lock(&logMutex); - + va_start(ap, format); snprintf(t, sizeBuffer, "SEDUATMO: "); vsnprintf(t+strlen(t), sizeBuffer-strlen(t), format, ap); - + syslog(LOG_ERR, "%s", t); va_end(ap); @@ -67,6 +72,15 @@ int error(const char* format, ...) } //*************************************************************************** +// is Empty +//*************************************************************************** + +int isEmpty(const char* str) +{ + return !str || !*str; +} + +//*************************************************************************** // msNow //*************************************************************************** @@ -74,7 +88,7 @@ MsTime msNow() { timeval tv; - gettimeofday(&tv, 0); + gettimeofday(&tv, 0); return tv.tv_sec * 1000 + tv.tv_usec / 1000; } @@ -87,10 +101,10 @@ int minMax(int x, int min, int max) { if (x < min) return min; - + if (max < x) return max; - + return x; } @@ -109,3 +123,156 @@ int getrand(int min, int max) srand(time(0)); return rand() % (max-min) + min; } + +//*************************************************************************** +// Is Alive (fork ping therefore no root permissions needed) +//*************************************************************************** + +int isAlive(const char* address) +{ + return ping(address) == success; +} + +uint16_t cksum(uint16_t *addr, unsigned len) +{ + uint16_t answer = 0; + uint32_t sum = 0; + + while (len > 1) + { + sum += *addr++; + len -= 2; + } + + if (len == 1) + { + *(unsigned char *)&answer = *(unsigned char *)addr ; + sum += answer; + } + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + answer = ~sum; + + return answer; +} + +int ping(const char* target) +{ + const size_t DEFDATALEN = (64-ICMP_MINLEN); + const size_t MAXIPLEN = 60; + const size_t MAXICMPLEN = 76; + const size_t MAXPACKET = (65536 - 60 - ICMP_MINLEN); + + int i, cc, packlen, datalen = DEFDATALEN; + struct hostent *hp; + struct sockaddr_in to, from; + + u_char *packet, outpack[MAXPACKET]; + char hnamebuf[MAXHOSTNAMELEN]; + std::string hostname; + struct icmp *icp; + int ret, fromlen, hlen; + fd_set rfds; + struct timeval tv; + + to.sin_family = AF_INET; + to.sin_addr.s_addr = inet_addr(target); + + if (to.sin_addr.s_addr != (u_int)-1) + hostname = target; + else + { + if (!(hp = gethostbyname(target))) + { + tell(0, "unknown host '%s'", target); + return fail; + } + + to.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (caddr_t)&to.sin_addr, hp->h_length); + strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); + hostname = hnamebuf; + } + + packlen = datalen + MAXIPLEN + MAXICMPLEN; + packet = (u_char*)malloc((u_int)packlen); + + int sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + + if (sd < 0) + { + tell(0, "Error: sokett failed due to '%s'", strerror(errno)); + return fail; // Needs to run as root ore set rights "setcap cap_net_raw+ep /usr/bin/vdr" + } + + icp = (struct icmp*)outpack; + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = 12345; + icp->icmp_id = getpid(); + + cc = datalen + ICMP_MINLEN; + icp->icmp_cksum = cksum((unsigned short *)icp,cc); + i = sendto(sd, (char *)outpack, cc, 0, (struct sockaddr*)&to, (socklen_t)sizeof(struct sockaddr_in)); + + if (i < 0) + tell(0, "Error: Sendto '%s'", strerror(errno)); + + FD_ZERO(&rfds); + FD_SET(sd, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 50000; + + while (true) + { + int retval = select(sd+1, &rfds, NULL, NULL, &tv); + + if (retval <= 0) + { + if (retval == -1) + tell(0, "Error: select() '%s'", strerror(errno)); + + close(sd); + return fail; + } + + fromlen = sizeof(sockaddr_in); + + if ((ret = recvfrom(sd, (char*)packet, packlen, 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) < 0) + { + tell(0, "Error: recvfrom '%s'", strerror(errno)); + close(sd); + return fail; + } + + // Check the IP header + + hlen = sizeof(struct ip); + + if (ret < (hlen + ICMP_MINLEN)) + { + tell(0, "Packet too short (%d) bytes from '%s'", ret, hostname.c_str()); + close(sd); + return fail; + } + + // Now the ICMP part + + icp = (struct icmp*)(packet + hlen); + + if (icp->icmp_type == ICMP_ECHOREPLY) + { + if (icp->icmp_seq == 12345 && icp->icmp_id == getpid()) + { + close(sd); + return success; + } + } + } + + close(sd); + + return fail; +} |