/* ** L2 - OSSP Logging Library ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP L2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/l2/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** 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. ** ** l2_sockmon.c: Socket monitor for use with l2_test.c */ #include #include #include #include #include #include #include "l2.h" #define BACKLOG 1024 /* max # pending connections */ #define BUFFSIZ 256 /* max string size */ char *strlowerdup(const char *pszIn) { int i = 0; char *pszTemp = NULL; assert(pszIn != NULL); if ((pszTemp = (char *)strdup(pszIn)) == NULL) return NULL; else { for (i = 0; *(pszTemp + i); i++) if (isupper(*(pszTemp + i))) *(pszTemp + i) = (char)tolower(*(pszTemp + i)); return pszTemp; } } void dowork(int iSock) { char pszBuf[BUFFSIZ]; int cc; while (1) { /* Exits when read finishes */ cc = read(iSock, pszBuf, sizeof (pszBuf)); if (cc == -1) { perror("read"); exit(1); } if (cc == 0) { /* EOF */ (void) close(iSock); (void) printf("Connection closed\n"); return; } pszBuf[cc + 1] = '\0'; (void) printf("Read: %s", pszBuf); if (write(iSock, pszBuf, cc) == -1) { perror("write"); exit(1); } } } int myserver(int iFamily, int iProtocol, int iPort) { char pszBuf[BUFFSIZ]; struct sockaddr_in laddr4, faddr4, caddr4; struct sockaddr_in6 laddr6, faddr6, caddr6; int iSock, iNewsock; int iSockopt, iProtofam; int iTrans, cc; socklen_t faddrlen; /* Set up an IPv4 TCP socket to listen on for connections. */ if (iFamily == AF_INET6) { /* initialize address structure */ memset(&laddr6, 0, sizeof(laddr6)); laddr6.sin6_family = AF_INET6; laddr6.sin6_flowinfo = 0; laddr6.sin6_port = iPort; laddr6.sin6_addr = in6addr_any; /* Structure assignment */ } else if (iFamily == AF_INET) { /* initialize address structure */ memset(&laddr4, 0, sizeof(laddr4)); laddr4.sin_family = AF_INET; laddr4.sin_port = iPort; laddr4.sin_addr.s_addr = INADDR_ANY; } else return -1; /* Not IPv4 or IPv6 */ iProtofam = (iFamily == AF_INET) ? PF_INET : PF_INET6; iTrans = (iProtocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; iSock = socket(iProtofam, iTrans, iProtocol); if (iSock == -1) { perror("socket"); return -1; } /* Tell the system to allow local addresses to be reused. */ iSockopt = 1; if (setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, (void *)&iSockopt,\ sizeof (iSockopt)) == -1) { perror("setsockopt(SO_REUSEADDR)"); (void) close(iSock); return -1; } if (iFamily == AF_INET6) { if (bind(iSock, (struct sockaddr *)&laddr6, sizeof (laddr6)) == -1) { perror("bind"); /* Bad bind */ (void) close(iSock); return -1; } } else if (iFamily == AF_INET) { if (bind(iSock, (struct sockaddr *)&laddr4, sizeof (laddr4)) == -1) { perror("bind"); /* Bad bind */ (void) close(iSock); return -1; } } if (iProtocol == IPPROTO_UDP) { if (iFamily == AF_INET6) { /* initialize address structure */ memset(&caddr6, 0, sizeof(caddr6)); for (;;) { /* Receive messages */ faddrlen = sizeof(caddr6); memset(pszBuf, 0x0, BUFFSIZ); /* Init the buffer */ cc = recvfrom(iSock, pszBuf, BUFFSIZ, 0, (struct sockaddr *)\ &caddr6, &faddrlen); if (cc == -1) { perror("recvfrom"); exit(1); } if (cc == 0) { /* EOF */ (void) close(iSock); (void) printf("Connection closed\n"); return; } if (cc != BUFFSIZ) { pszBuf[cc + 1] = '\0'; (void) printf("Read: %s", pszBuf); if (write(iSock, pszBuf, cc) == -1) { perror("write"); exit(1); } } else return -1; } } else if (iFamily == AF_INET) { /* initialize address structure */ memset(&caddr4, 0, sizeof(caddr4)); for (;;) { /* Receive messages */ faddrlen = sizeof(caddr4); memset(pszBuf, 0x0, BUFFSIZ); /* Init the buffer */ cc = recvfrom(iSock, pszBuf, BUFFSIZ, 0, (struct sockaddr *)\ &caddr4, &faddrlen); if (cc == -1) { perror("recvfrom"); exit(1); } if (cc == 0) { /* EOF */ (void) close(iSock); (void) printf("Connection closed\n"); return; } if (cc != BUFFSIZ) { pszBuf[cc + 1] = '\0'; (void) printf("Read: %s", pszBuf); if (write(iSock, pszBuf, cc) == -1) { perror("write"); exit(1); } } else return -1; } } } else if (iProtocol == IPPROTO_TCP) { /* Only try to listen if we have TCP */ if (listen(iSock, BACKLOG) == -1) { perror("listen"); /* Listen just blew up */ (void) close(iSock); return -1; } /* Wait for a connection request */ if (iFamily == AF_INET6) { /* initialize address structure */ memset(&faddr6, 0, sizeof(faddr6)); for (;;) { faddrlen = sizeof (faddr6); iNewsock = accept(iSock, (struct sockaddr *)&faddr6, &faddrlen); if (iNewsock == -1) { if (errno != EINTR && errno != ECONNABORTED) { perror("accept"); } continue; } (void) printf("Connection from %s/%d\n",\ inet_ntop(faddr6.sin6_addr), ntohs(faddr6.sin6_port)); dowork(iNewsock); /* do some sockwork */ } } else if (iFamily == AF_INET) { /* initialize address structure */ memset(&faddr4, 0, sizeof(faddr4)); for (;;) { faddrlen = sizeof (faddr4); iNewsock = accept(iSock, (struct sockaddr *)&faddr4, &faddrlen); if (iNewsock == -1) { if (errno != EINTR && errno != ECONNABORTED) { perror("accept"); } continue; } (void) printf("Connection from %s/%d\n",\ inet_ntop(faddr4.sin_addr), ntohs(faddr4.sin_port)); dowork(iNewsock); /* do some sockwork */ } } /* NOTREACHED */ } else return -1; /* We are being asked to serve other than TCP or UDP */ } int main(int argc, char *argv[]) { int iFam = -1; int iProto = -1; int iPort = 0; if (argc != 4) { (void) fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); /* Dink donk if the user doesn't know how to use this */ } iFam = (!strcmp(argv[1], "IPv6")) ? AF_INET6 : AF_INET; iProto = (!strcmp(argv[2], "UDP")) ? IPPROTO_UDP : IPPROTO_TCP; iPort = htons(atoi(argv[3])); return myserver(iFam, iProto, iPort); }