basic tcp handling (missing files)
This commit is contained in:
parent
be0608c451
commit
f5d8287cc6
101
logging.c
Normal file
101
logging.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 07/2007 by Olaf Rempel *
|
||||||
|
* razzor@kopf-tisch.de *
|
||||||
|
* *
|
||||||
|
* 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; version 2 of the License *
|
||||||
|
* *
|
||||||
|
* 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, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
#define BUFSIZE 8192
|
||||||
|
|
||||||
|
static FILE *log_fd = NULL;
|
||||||
|
static int log_prio = LOG_EVERYTIME;
|
||||||
|
static char *buffer = NULL;
|
||||||
|
|
||||||
|
int log_print(int prio, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list az;
|
||||||
|
int len = 0, retval;
|
||||||
|
|
||||||
|
if (prio < log_prio)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
buffer = malloc(BUFSIZE);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
fprintf(stderr, "log_print(): out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_fd != NULL) {
|
||||||
|
time_t tzgr;
|
||||||
|
time(&tzgr);
|
||||||
|
|
||||||
|
len += strftime(buffer, BUFSIZE, "%b %d %H:%M:%S :", localtime(&tzgr));
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(az, fmt);
|
||||||
|
len += vsnprintf(buffer + len, BUFSIZE - len, fmt, az);
|
||||||
|
va_end(az);
|
||||||
|
|
||||||
|
if (len < 0 || len >= BUFSIZE) {
|
||||||
|
errno = 0;
|
||||||
|
return log_print(LOG_ERROR, "log_print: arguments too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno) {
|
||||||
|
len += snprintf(buffer + len, BUFSIZE - len, ": %s", strerror(errno));
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = fprintf((log_fd ? log_fd : stderr), "%s\n", buffer);
|
||||||
|
fflush(log_fd);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_close(void)
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (log_fd)
|
||||||
|
fclose(log_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int log_init(const char *logfile)
|
||||||
|
{
|
||||||
|
if (log_fd != NULL)
|
||||||
|
log_close();
|
||||||
|
|
||||||
|
log_fd = fopen(logfile, "a");
|
||||||
|
if (log_fd == NULL) {
|
||||||
|
fprintf(stderr, "log_init(): can not open logfile");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_setprio(int prio)
|
||||||
|
{
|
||||||
|
log_prio = prio;
|
||||||
|
}
|
19
logging.h
Normal file
19
logging.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _LOGGING_H_
|
||||||
|
#define _LOGGING_H_
|
||||||
|
|
||||||
|
#define LOG_DEBUG 5
|
||||||
|
#define LOG_INFO 4
|
||||||
|
#define LOG_NOTICE 3
|
||||||
|
#define LOG_WARN 2
|
||||||
|
#define LOG_ERROR 1
|
||||||
|
#define LOG_CRIT 0
|
||||||
|
|
||||||
|
#define LOG_EVERYTIME 0
|
||||||
|
|
||||||
|
int log_init(const char *logfile);
|
||||||
|
void log_close(void);
|
||||||
|
void log_setprio(int prio);
|
||||||
|
|
||||||
|
int log_print(int prio, const char *fmt, ... );
|
||||||
|
|
||||||
|
#endif /* _LOGGING_H_ */
|
117
sockaddr.c
Normal file
117
sockaddr.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 07/2007 by Olaf Rempel *
|
||||||
|
* razzor@kopf-tisch.de *
|
||||||
|
* *
|
||||||
|
* 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; version 2 of the License *
|
||||||
|
* *
|
||||||
|
* 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, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
int parse_sockaddr(const char *addr, struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
char *buf = strdup(addr);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char *tmp;
|
||||||
|
char *ipstr = strtok_r(buf, ":", &tmp);
|
||||||
|
if (ipstr == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sa->sin_family = AF_INET;
|
||||||
|
if (inet_pton(AF_INET, ipstr, &sa->sin_addr) <= 0) {
|
||||||
|
free(buf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *portstr = strtok_r(NULL, " \r\n", &tmp);
|
||||||
|
if (portstr == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = atoi(portstr);
|
||||||
|
if (port < 0 || port > 65535) {
|
||||||
|
free(buf);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
sa->sin_port = htons(port);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask)
|
||||||
|
{
|
||||||
|
char *buf = strdup(addr);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char *tmp;
|
||||||
|
char *netstr = strtok_r(buf, "/", &tmp);
|
||||||
|
if (netstr == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, netstr, net) <= 0) {
|
||||||
|
free(buf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *maskstr = strtok_r(NULL, " \r\n", &tmp);
|
||||||
|
if (maskstr == NULL) {
|
||||||
|
mask->s_addr = ~0;
|
||||||
|
|
||||||
|
} else if (inet_pton(AF_INET, maskstr, mask) <= 0) {
|
||||||
|
int maskbits = atoi(maskstr);
|
||||||
|
if (maskbits < 0 || maskbits > 32) {
|
||||||
|
free(buf);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
mask->s_addr = htonl(~0 << (32 - maskbits));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_sockaddr(char *buf, int size, struct sockaddr_in *addr)
|
||||||
|
{
|
||||||
|
return snprintf(buf, size, "%s:%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
char * get_sockaddr_buf(struct sockaddr_in *addr)
|
||||||
|
{
|
||||||
|
static char ret[24];
|
||||||
|
get_sockaddr(ret, sizeof(ret), addr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b)
|
||||||
|
{
|
||||||
|
return !((a->sin_family ^ b->sin_family) |
|
||||||
|
(a->sin_addr.s_addr ^ b->sin_addr.s_addr) |
|
||||||
|
(a->sin_port ^ b->sin_port));
|
||||||
|
}
|
14
sockaddr.h
Normal file
14
sockaddr.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _SOCKADDR_H_
|
||||||
|
#define _SOCKADDR_H_
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
int parse_sockaddr(const char *addr, struct sockaddr_in *sa);
|
||||||
|
int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask);
|
||||||
|
|
||||||
|
int get_sockaddr(char *buf, int size, struct sockaddr_in *addr);
|
||||||
|
char * get_sockaddr_buf(struct sockaddr_in *addr);
|
||||||
|
|
||||||
|
int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b);
|
||||||
|
|
||||||
|
#endif /* _SOCKADDR_H_ */
|
135
tcpsocket.c
Normal file
135
tcpsocket.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 07/2007 by Olaf Rempel *
|
||||||
|
* razzor@kopf-tisch.de *
|
||||||
|
* *
|
||||||
|
* 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; version 2 of the License *
|
||||||
|
* *
|
||||||
|
* 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, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
|
#include "sockaddr.h"
|
||||||
|
|
||||||
|
int tcp_listen(struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0 ) {
|
||||||
|
log_print(LOG_ERROR, "tcp_listen_socket(): socket()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i))) {
|
||||||
|
log_print(LOG_ERROR, "tcp_listen_socket(): setsockopt(SO_REUSEADDR)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(sock, (struct sockaddr *)sa, sizeof(*sa))) {
|
||||||
|
log_print(LOG_ERROR, "tcp_listen_socket(): bind(%s)", get_sockaddr_buf(sa));
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(sock, 8)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_listen_socket(): listen()");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_connect(struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0 ) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_socket(): socket()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = connect(sock, (struct sockaddr *)sa, sizeof(*sa));
|
||||||
|
if (ret != 0) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect(): connect(%s)", get_sockaddr_buf(sa));
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_connect_nonblock(struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0 ) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_nonblock(): socket()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = fcntl(sock, F_GETFL, 0);
|
||||||
|
if (flags < 0) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_nonblock(): fcntl(F_GETFL)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non-blocking connect() */
|
||||||
|
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_nonblock(): fcntl(F_SETFL)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = connect(sock, (struct sockaddr *)sa, sizeof(*sa));
|
||||||
|
if (ret && errno != EINPROGRESS) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_nonblock(): connect(%s)", get_sockaddr_buf(sa));
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset EINPROGRESS */
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
/* all further actions are blocking */
|
||||||
|
if (fcntl(sock, F_SETFL, flags)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_nonblock(): fcntl(F_SETFL)");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_connect_error(int fd)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int err_size = sizeof(err);
|
||||||
|
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_size)) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_error(): getsockopt(SO_ERROR)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
errno = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
12
tcpsocket.h
Normal file
12
tcpsocket.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _TCPSOCKET_H_
|
||||||
|
#define _TCPSOCKET_H_
|
||||||
|
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
|
int tcp_listen(struct sockaddr_in *sa);
|
||||||
|
int tcp_connect(struct sockaddr_in *sa);
|
||||||
|
|
||||||
|
int tcp_connect_nonblock(struct sockaddr_in *sa);
|
||||||
|
int tcp_connect_error(int fd);
|
||||||
|
|
||||||
|
#endif // _TCPSOCKET_H_
|
Loading…
Reference in New Issue
Block a user