Browse Source

basic tcp handling (missing files)

master
Olaf Rempel 11 years ago
parent
commit
f5d8287cc6
6 changed files with 398 additions and 0 deletions
  1. +101
    -0
      logging.c
  2. +19
    -0
      logging.h
  3. +117
    -0
      sockaddr.c
  4. +14
    -0
      sockaddr.h
  5. +135
    -0
      tcpsocket.c
  6. +12
    -0
      tcpsocket.h

+ 101
- 0
logging.c View 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
- 0
logging.h View 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
- 0
sockaddr.c View 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
- 0
sockaddr.h View 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
- 0
tcpsocket.c View 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
- 0
tcpsocket.h View 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…
Cancel
Save