|
a/src/netcon.cpp |
|
b/src/netcon.cpp |
|
... |
|
... |
29 |
#endif // _AIX
|
29 |
#endif // _AIX
|
30 |
|
30 |
|
31 |
#include <unistd.h>
|
31 |
#include <unistd.h>
|
32 |
#include <fcntl.h>
|
32 |
#include <fcntl.h>
|
33 |
#include <sys/time.h>
|
33 |
#include <sys/time.h>
|
34 |
|
|
|
35 |
#include <sys/socket.h>
|
34 |
#include <sys/socket.h>
|
|
|
35 |
#include <sys/un.h>
|
36 |
#include <netinet/in.h>
|
36 |
#include <netinet/in.h>
|
37 |
#include <netinet/tcp.h>
|
37 |
#include <netinet/tcp.h>
|
38 |
#include <arpa/inet.h>
|
38 |
#include <arpa/inet.h>
|
39 |
#include <netdb.h>
|
39 |
#include <netdb.h>
|
40 |
|
40 |
|
|
... |
|
... |
59 |
|
59 |
|
60 |
#include "netcon.h"
|
60 |
#include "netcon.h"
|
61 |
|
61 |
|
62 |
#ifndef SOCKLEN_T
|
62 |
#ifndef SOCKLEN_T
|
63 |
#define SOCKLEN_T socklen_t
|
63 |
#define SOCKLEN_T socklen_t
|
|
|
64 |
#endif
|
|
|
65 |
|
|
|
66 |
// Size of path buffer in sockaddr_un (AF_UNIX socket
|
|
|
67 |
// addr). Mysteriously it's 108 (explicit value) under linux, no
|
|
|
68 |
// define accessible. Let's take a little margin as it appears that
|
|
|
69 |
// some systems use 92. I believe we could also malloc a variable size
|
|
|
70 |
// struct but why bother.
|
|
|
71 |
#ifndef UNIX_PATH_MAX
|
|
|
72 |
#define UNIX_PATH_MAX 90
|
64 |
#endif
|
73 |
#endif
|
65 |
|
74 |
|
66 |
// Need &one, &zero for setsockopt...
|
75 |
// Need &one, &zero for setsockopt...
|
67 |
static const int one = 1;
|
76 |
static const int one = 1;
|
68 |
static const int zero = 0;
|
77 |
static const int zero = 0;
|
|
... |
|
... |
613 |
int ret = -1;
|
622 |
int ret = -1;
|
614 |
LOGDEB2(("Netconcli::openconn: host %s, port %d\n", host, port));
|
623 |
LOGDEB2(("Netconcli::openconn: host %s, port %d\n", host, port));
|
615 |
|
624 |
|
616 |
closeconn();
|
625 |
closeconn();
|
617 |
|
626 |
|
|
|
627 |
struct sockaddr *saddr;
|
|
|
628 |
socklen_t addrsize;
|
|
|
629 |
|
618 |
struct sockaddr_in saddr;
|
630 |
struct sockaddr_in ip_addr;
|
|
|
631 |
struct sockaddr_un unix_addr;
|
|
|
632 |
if (host[0] != '/') {
|
619 |
memset(&saddr, 0, sizeof(saddr));
|
633 |
memset(&ip_addr, 0, sizeof(ip_addr));
|
620 |
saddr.sin_family = AF_INET;
|
634 |
ip_addr.sin_family = AF_INET;
|
621 |
saddr.sin_port = htons(port);
|
635 |
ip_addr.sin_port = htons(port);
|
622 |
|
636 |
|
623 |
// Server name may be host name or IP address
|
637 |
// Server name may be host name or IP address
|
624 |
int addr;
|
638 |
int addr;
|
625 |
if ((addr = inet_addr(host)) != -1) {
|
639 |
if ((addr = inet_addr(host)) != -1) {
|
626 |
memcpy(&saddr.sin_addr, &addr, sizeof(addr));
|
640 |
memcpy(&ip_addr.sin_addr, &addr, sizeof(addr));
|
|
|
641 |
} else {
|
|
|
642 |
struct hostent *hp;
|
|
|
643 |
if ((hp = gethostbyname(host)) == 0) {
|
|
|
644 |
LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n",
|
|
|
645 |
host));
|
|
|
646 |
return -1;
|
|
|
647 |
}
|
|
|
648 |
memcpy(&ip_addr.sin_addr, hp->h_addr, hp->h_length);
|
|
|
649 |
}
|
|
|
650 |
|
|
|
651 |
if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
|
652 |
LOGSYSERR("NetconCli::openconn", "socket", "");
|
|
|
653 |
return -1;
|
|
|
654 |
}
|
|
|
655 |
addrsize = sizeof(ip_addr);
|
|
|
656 |
saddr = (sockaddr*)&ip_addr;
|
627 |
} else {
|
657 |
} else {
|
628 |
struct hostent *hp;
|
658 |
memset(&unix_addr, 0, sizeof(unix_addr));
|
629 |
if ((hp = gethostbyname(host)) == 0) {
|
659 |
unix_addr.sun_family = AF_UNIX;
|
|
|
660 |
if (strlen(host) > UNIX_PATH_MAX - 1) {
|
630 |
LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n", host));
|
661 |
LOGERR(("NetconCli::openconn: name too long: %s\n", host));
|
631 |
return -1;
|
662 |
return -1;
|
632 |
}
|
|
|
633 |
memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
|
|
|
634 |
}
|
663 |
}
|
|
|
664 |
strcpy(unix_addr.sun_path, host);
|
635 |
|
665 |
|
636 |
if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
666 |
if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
637 |
LOGSYSERR("NetconCli::openconn", "socket", "");
|
667 |
LOGSYSERR("NetconCli::openconn", "socket", "");
|
638 |
return -1;
|
668 |
return -1;
|
|
|
669 |
}
|
|
|
670 |
addrsize = sizeof(unix_addr);
|
|
|
671 |
saddr = (sockaddr*)&unix_addr;
|
639 |
}
|
672 |
}
|
640 |
if (timeo > 0) {
|
673 |
if (timeo > 0) {
|
641 |
set_nonblock(1);
|
674 |
set_nonblock(1);
|
642 |
}
|
675 |
}
|
643 |
|
676 |
|
644 |
if (connect(m_fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
|
677 |
if (connect(m_fd, saddr, addrsize) < 0) {
|
645 |
if (timeo > 0) {
|
678 |
if (timeo > 0) {
|
646 |
if (errno != EINPROGRESS) {
|
679 |
if (errno != EINPROGRESS) {
|
647 |
goto out;
|
680 |
goto out;
|
648 |
}
|
681 |
}
|
649 |
if (select1(m_fd, timeo, 1) == 1) {
|
682 |
if (select1(m_fd, timeo, 1) == 1) {
|
|
... |
|
... |
674 |
}
|
707 |
}
|
675 |
return ret;
|
708 |
return ret;
|
676 |
}
|
709 |
}
|
677 |
|
710 |
|
678 |
// Same as previous, but get the port number from services
|
711 |
// Same as previous, but get the port number from services
|
679 |
int NetconCli::openconn(const char *host, char *serv, int timeo)
|
712 |
int NetconCli::openconn(const char *host, const char *serv, int timeo)
|
680 |
{
|
713 |
{
|
681 |
LOGDEB2(("Netconcli::openconn: host %s, serv %s\n", host, serv));
|
714 |
LOGDEB2(("Netconcli::openconn: host %s, serv %s\n", host, serv));
|
682 |
|
715 |
|
|
|
716 |
if (host[0] != '/') {
|
683 |
struct servent *sp;
|
717 |
struct servent *sp;
|
684 |
if ((sp = getservbyname(serv, "tcp")) == 0) {
|
718 |
if ((sp = getservbyname(serv, "tcp")) == 0) {
|
685 |
LOGERR(("NetconCli::openconn: getservbyname failed for %s\n", serv));
|
719 |
LOGERR(("NetconCli::openconn: getservbyname failed for %s\n",serv));
|
686 |
return -1;
|
720 |
return -1;
|
687 |
}
|
721 |
}
|
688 |
// Callee expects the port number in host byte order
|
722 |
// Callee expects the port number in host byte order
|
689 |
return openconn(host, ntohs(sp->s_port), timeo);
|
723 |
return openconn(host, ntohs(sp->s_port), timeo);
|
|
|
724 |
} else {
|
|
|
725 |
return openconn(host, (unsigned int)0, timeo);
|
|
|
726 |
}
|
690 |
}
|
727 |
}
|
691 |
|
728 |
|
692 |
|
729 |
|
693 |
int NetconCli::setconn(int fd)
|
730 |
int NetconCli::setconn(int fd)
|
694 |
{
|
731 |
{
|
|
... |
|
... |
725 |
fprintf(stderr, "Proto %s\n", servp->s_proto);
|
762 |
fprintf(stderr, "Proto %s\n", servp->s_proto);
|
726 |
}
|
763 |
}
|
727 |
#endif
|
764 |
#endif
|
728 |
|
765 |
|
729 |
// Set up service.
|
766 |
// Set up service.
|
730 |
int NetconServLis::openservice(char *serv, int backlog)
|
767 |
int NetconServLis::openservice(const char *serv, int backlog)
|
731 |
{
|
768 |
{
|
732 |
int port;
|
769 |
int port;
|
733 |
struct servent *servp;
|
770 |
struct servent *servp;
|
|
|
771 |
if (!serv) {
|
|
|
772 |
LOGERR(("NetconServLis::openservice: null serv??\n"));
|
|
|
773 |
return -1;
|
|
|
774 |
}
|
734 |
LOGDEB1(("NetconServLis::openservice: serv %s\n", serv));
|
775 |
LOGDEB1(("NetconServLis::openservice: serv %s\n", serv));
|
735 |
#ifdef NETCON_ACCESSCONTROL
|
776 |
#ifdef NETCON_ACCESSCONTROL
|
736 |
if (initperms(serv) < 0) {
|
777 |
if (initperms(serv) < 0) {
|
737 |
return -1;
|
778 |
return -1;
|
738 |
}
|
779 |
}
|
739 |
#endif
|
780 |
#endif
|
|
|
781 |
|
|
|
782 |
m_serv = serv;
|
|
|
783 |
if (serv[0] != '/') {
|
740 |
if ((servp = getservbyname(serv, "tcp")) == 0) {
|
784 |
if ((servp = getservbyname(serv, "tcp")) == 0) {
|
741 |
LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n", serv));
|
785 |
LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n",
|
|
|
786 |
serv));
|
742 |
return -1;
|
787 |
return -1;
|
743 |
}
|
788 |
}
|
744 |
port = (int)ntohs((short)servp->s_port);
|
789 |
port = (int)ntohs((short)servp->s_port);
|
745 |
return openservice(port, backlog);
|
790 |
return openservice(port, backlog);
|
|
|
791 |
} else {
|
|
|
792 |
if (strlen(serv) > UNIX_PATH_MAX - 1) {
|
|
|
793 |
LOGERR(("NetconServLis::openservice: too long for AF_UNIX: %s\n",
|
|
|
794 |
serv));
|
|
|
795 |
return -1;
|
|
|
796 |
}
|
|
|
797 |
int ret = -1;
|
|
|
798 |
struct sockaddr_un addr;
|
|
|
799 |
if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
|
800 |
LOGSYSERR("NetconServLis", "socket", "");
|
|
|
801 |
return -1;
|
|
|
802 |
}
|
|
|
803 |
memset(&addr, 0, sizeof(addr));
|
|
|
804 |
addr.sun_family = AF_UNIX;
|
|
|
805 |
strcpy(addr.sun_path, serv);
|
|
|
806 |
|
|
|
807 |
if (::bind(m_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
808 |
LOGSYSERR("NetconServLis", "bind", "");
|
|
|
809 |
goto out;
|
|
|
810 |
}
|
|
|
811 |
if (listen(m_fd, backlog) < 0) {
|
|
|
812 |
LOGSYSERR("NetconServLis", "listen", "");
|
|
|
813 |
goto out;
|
|
|
814 |
}
|
|
|
815 |
|
|
|
816 |
LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
|
|
|
817 |
ret = 0;
|
|
|
818 |
out:
|
|
|
819 |
if (ret < 0 && m_fd >= 0) {
|
|
|
820 |
close(m_fd);
|
|
|
821 |
m_fd = -1;
|
|
|
822 |
}
|
|
|
823 |
return ret;
|
|
|
824 |
}
|
746 |
}
|
825 |
}
|
747 |
|
826 |
|
748 |
// Port is a natural host integer value
|
827 |
// Port is a natural host integer value
|
749 |
int NetconServLis::openservice(int port, int backlog)
|
828 |
int NetconServLis::openservice(int port, int backlog)
|
750 |
{
|
829 |
{
|
|
... |
|
... |
798 |
sprintf(sport, "%d", port);
|
877 |
sprintf(sport, "%d", port);
|
799 |
return initperms(sport);
|
878 |
return initperms(sport);
|
800 |
}
|
879 |
}
|
801 |
|
880 |
|
802 |
// Get authorized address lists from parameter file. This is disabled for now
|
881 |
// Get authorized address lists from parameter file. This is disabled for now
|
803 |
int NetconServLis::initperms(char *serv)
|
882 |
int NetconServLis::initperms(const char *serv)
|
804 |
{
|
883 |
{
|
805 |
if (permsinit) {
|
884 |
if (permsinit) {
|
806 |
return 0;
|
885 |
return 0;
|
807 |
}
|
886 |
}
|
808 |
|
887 |
|
|
... |
|
... |
866 |
m_didtimo = 0;
|
945 |
m_didtimo = 0;
|
867 |
|
946 |
|
868 |
NetconServCon *con = 0;
|
947 |
NetconServCon *con = 0;
|
869 |
int newfd = -1;
|
948 |
int newfd = -1;
|
870 |
struct sockaddr_in who;
|
949 |
struct sockaddr_in who;
|
|
|
950 |
struct sockaddr_un uwho;
|
|
|
951 |
if (m_serv.empty() || m_serv[0] != '/') {
|
871 |
SOCKLEN_T clilen = (SOCKLEN_T)sizeof(who);
|
952 |
SOCKLEN_T clilen = (SOCKLEN_T)sizeof(who);
|
872 |
if ((newfd = ::accept(m_fd, (struct sockaddr *)&who, &clilen)) < 0) {
|
953 |
if ((newfd = ::accept(m_fd, (struct sockaddr *)&who, &clilen)) < 0) {
|
873 |
LOGSYSERR("NetconServCon::accept", "accept", "");
|
954 |
LOGSYSERR("NetconServCon::accept", "accept", "");
|
874 |
goto out;
|
955 |
goto out;
|
875 |
}
|
956 |
}
|
876 |
#ifdef NETCON_ACCESSCONTROL
|
957 |
#ifdef NETCON_ACCESSCONTROL
|
877 |
if (checkperms(&who, clilen) < 0) {
|
958 |
if (checkperms(&who, clilen) < 0) {
|
878 |
goto out;
|
959 |
goto out;
|
879 |
}
|
960 |
}
|
880 |
#endif
|
961 |
#endif
|
|
|
962 |
} else {
|
|
|
963 |
SOCKLEN_T clilen = (SOCKLEN_T)sizeof(uwho);
|
|
|
964 |
if ((newfd = ::accept(m_fd, (struct sockaddr *)&uwho, &clilen)) < 0) {
|
|
|
965 |
LOGSYSERR("NetconServCon::accept", "accept", "");
|
|
|
966 |
goto out;
|
|
|
967 |
}
|
|
|
968 |
}
|
|
|
969 |
|
881 |
con = new NetconServCon(newfd);
|
970 |
con = new NetconServCon(newfd);
|
882 |
if (con == 0) {
|
971 |
if (con == 0) {
|
883 |
LOGERR(("NetconServLis::accept: new NetconServCon failed\n"));
|
972 |
LOGERR(("NetconServLis::accept: new NetconServCon failed\n"));
|
884 |
goto out;
|
973 |
goto out;
|
885 |
}
|
974 |
}
|
|
|
975 |
|
886 |
// Retrieve peer's host name. Errors are non fatal
|
976 |
// Retrieve peer's host name. Errors are non fatal
|
|
|
977 |
if (m_serv.empty() || m_serv[0] != '/') {
|
887 |
struct hostent *hp;
|
978 |
struct hostent *hp;
|
888 |
if ((hp = gethostbyaddr((char *) & (who.sin_addr), sizeof(struct in_addr),
|
979 |
if ((hp = gethostbyaddr((char *) & (who.sin_addr),
|
889 |
AF_INET)) == 0) {
|
980 |
sizeof(struct in_addr), AF_INET)) == 0) {
|
890 |
LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n",
|
981 |
LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n",
|
891 |
who.sin_addr.s_addr));
|
982 |
who.sin_addr.s_addr));
|
892 |
con->setpeer(inet_ntoa(who.sin_addr));
|
983 |
con->setpeer(inet_ntoa(who.sin_addr));
|
|
|
984 |
} else {
|
|
|
985 |
con->setpeer(hp->h_name);
|
|
|
986 |
}
|
893 |
} else {
|
987 |
} else {
|
894 |
con->setpeer(hp->h_name);
|
988 |
con->setpeer(m_serv.c_str());
|
895 |
}
|
989 |
}
|
|
|
990 |
|
896 |
LOGDEB2(("NetconServLis::accept: setting keepalive\n"));
|
991 |
LOGDEB2(("NetconServLis::accept: setting keepalive\n"));
|
897 |
if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE,
|
992 |
if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE,
|
898 |
(char *)&one, sizeof(one)) < 0) {
|
993 |
(char *)&one, sizeof(one)) < 0) {
|
899 |
LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE");
|
994 |
LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE");
|
900 |
}
|
995 |
}
|
|
... |
|
... |
1104 |
NetconP con(clicon);
|
1199 |
NetconP con(clicon);
|
1105 |
if (!con) {
|
1200 |
if (!con) {
|
1106 |
fprintf(stderr, "new NetconCli failed\n");
|
1201 |
fprintf(stderr, "new NetconCli failed\n");
|
1107 |
return 1;
|
1202 |
return 1;
|
1108 |
}
|
1203 |
}
|
1109 |
if (clicon->openconn(host, serv) < 0) {
|
1204 |
int port = atoi(serv);
|
|
|
1205 |
int ret = port > 0 ?
|
|
|
1206 |
clicon->openconn(host, port) : clicon->openconn(host, serv);
|
|
|
1207 |
if (ret < 0) {
|
1110 |
fprintf(stderr, "openconn(%s, %s) failed\n", host, serv);
|
1208 |
fprintf(stderr, "openconn(%s, %s) failed\n", host, serv);
|
1111 |
return 1;
|
1209 |
return 1;
|
1112 |
}
|
1210 |
}
|
1113 |
fprintf(stderr, "openconn(%s, %s) ok\n", host, serv);
|
1211 |
fprintf(stderr, "openconn(%s, %s) ok\n", host, serv);
|
1114 |
#ifdef NOSELLOOP
|
1212 |
#ifdef NOSELLOOP
|
|
... |
|
... |
1133 |
shared_ptr<CliNetconWorker> worker = make_shared<CliNetconWorker>();
|
1231 |
shared_ptr<CliNetconWorker> worker = make_shared<CliNetconWorker>();
|
1134 |
clicon->setcallback(worker);
|
1232 |
clicon->setcallback(worker);
|
1135 |
SelectLoop myloop;
|
1233 |
SelectLoop myloop;
|
1136 |
myloop.addselcon(con, Netcon::NETCONPOLL_WRITE);
|
1234 |
myloop.addselcon(con, Netcon::NETCONPOLL_WRITE);
|
1137 |
fprintf(stderr, "client ready\n");
|
1235 |
fprintf(stderr, "client ready\n");
|
1138 |
int ret = myloop.doLoop();
|
1236 |
ret = myloop.doLoop();
|
1139 |
if (ret < 0) {
|
1237 |
if (ret < 0) {
|
1140 |
fprintf(stderr, "selectloop failed\n");
|
1238 |
fprintf(stderr, "selectloop failed\n");
|
1141 |
exit(1);
|
1239 |
exit(1);
|
1142 |
}
|
1240 |
}
|
1143 |
fprintf(stderr, "selectloop returned %d\n", ret);
|
1241 |
fprintf(stderr, "selectloop returned %d\n", ret);
|
|
... |
|
... |
1235 |
sigemptyset(&sa.sa_mask);
|
1333 |
sigemptyset(&sa.sa_mask);
|
1236 |
sigaction(SIGINT, &sa, 0);
|
1334 |
sigaction(SIGINT, &sa, 0);
|
1237 |
sigaction(SIGQUIT, &sa, 0);
|
1335 |
sigaction(SIGQUIT, &sa, 0);
|
1238 |
sigaction(SIGTERM, &sa, 0);
|
1336 |
sigaction(SIGTERM, &sa, 0);
|
1239 |
|
1337 |
|
1240 |
if (servlis->openservice(serv) < 0) {
|
1338 |
int port = atoi(serv);
|
|
|
1339 |
int ret = port > 0 ?
|
|
|
1340 |
servlis->openservice(port) : servlis->openservice(serv);
|
|
|
1341 |
if (ret < 0) {
|
1241 |
fprintf(stderr, "openservice(%s) failed\n", serv);
|
1342 |
fprintf(stderr, "openservice(%s) failed\n", serv);
|
1242 |
return 1;
|
1343 |
return 1;
|
1243 |
}
|
1344 |
}
|
1244 |
myloop.addselcon(lis, Netcon::NETCONPOLL_READ);
|
1345 |
myloop.addselcon(lis, Netcon::NETCONPOLL_READ);
|
1245 |
fprintf(stderr, "openservice(%s) Ok\n", serv);
|
1346 |
fprintf(stderr, "openservice(%s) Ok\n", serv);
|