Start of massive refactor
This commit is contained in:
		
							parent
							
								
									0f37a37775
								
							
						
					
					
						commit
						fa3f4a2e0e
					
				
					 10 changed files with 490 additions and 455 deletions
				
			
		| 
						 | 
				
			
			@ -18,12 +18,12 @@ typedef struct _patty_ax25_addr {
 | 
			
		|||
 | 
			
		||||
#pragma pack(pop)
 | 
			
		||||
 | 
			
		||||
typedef struct _patty_ax25    patty_ax25;
 | 
			
		||||
typedef struct _patty_ax25_if patty_ax25_if;
 | 
			
		||||
 | 
			
		||||
#include <patty/ax25/macros.h>
 | 
			
		||||
#include <patty/ax25/proto.h>
 | 
			
		||||
#include <patty/ax25/frame.h>
 | 
			
		||||
#include <patty/ax25/server.h>
 | 
			
		||||
#include <patty/ax25/if.h>
 | 
			
		||||
 | 
			
		||||
#define PATTY_AX25_ADDRESS_SIZE 7
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,8 @@ enum patty_ax25_sock_mode {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
enum patty_ax25_sock_opts {
 | 
			
		||||
    PATTY_AX25_SOCK_NONBLOCK = 1 << 0
 | 
			
		||||
    PATTY_AX25_SOCK_NONBLOCK = 1 << 0,
 | 
			
		||||
    PATTY_AX25_SOCK_PTY      = 1 << 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _patty_ax25_sock {
 | 
			
		||||
| 
						 | 
				
			
			@ -73,24 +74,6 @@ typedef struct _patty_ax25_sock {
 | 
			
		|||
    unsigned int hops;
 | 
			
		||||
} patty_ax25_sock;
 | 
			
		||||
 | 
			
		||||
typedef struct _patty_ax25 {
 | 
			
		||||
    patty_list *ifaces;
 | 
			
		||||
 | 
			
		||||
    patty_dict *socks,
 | 
			
		||||
               *socks_by_addrpair;
 | 
			
		||||
 | 
			
		||||
    int fd,
 | 
			
		||||
        fdmax;
 | 
			
		||||
 | 
			
		||||
    fd_set fds,
 | 
			
		||||
           fds_r,
 | 
			
		||||
           fds_w;
 | 
			
		||||
} patty_ax25;
 | 
			
		||||
 | 
			
		||||
int patty_ax25_init(patty_ax25 *ax25);
 | 
			
		||||
 | 
			
		||||
void patty_ax25_stop(patty_ax25 *ax25);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_pton(const char *callsign,
 | 
			
		||||
                    uint8_t ssid,
 | 
			
		||||
                    patty_ax25_addr *addr);
 | 
			
		||||
| 
						 | 
				
			
			@ -100,50 +83,39 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
 | 
			
		|||
                    uint8_t *ssid,
 | 
			
		||||
                    size_t len);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_open(patty_ax25 *ax25, const char *ifname);
 | 
			
		||||
int patty_ax25_open(int server,
 | 
			
		||||
                    const char *ifname);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_socket(patty_ax25 *ax25);
 | 
			
		||||
int patty_ax25_socket(int server,
 | 
			
		||||
                      int sockopts);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_bind(patty_ax25 *ax25,
 | 
			
		||||
int patty_ax25_bind(int server,
 | 
			
		||||
                    int socket,
 | 
			
		||||
                    patty_ax25_addr *addr);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_listen(patty_ax25 *ax25,
 | 
			
		||||
int patty_ax25_listen(int server,
 | 
			
		||||
                      int socket);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_accept(patty_ax25 *ax25,
 | 
			
		||||
int patty_ax25_accept(int server,
 | 
			
		||||
                      int socket);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_connect(patty_ax25 *ax25,
 | 
			
		||||
int patty_ax25_connect(int server,
 | 
			
		||||
                       int socket,
 | 
			
		||||
                       patty_ax25_addr *addr);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_close(patty_ax25 *ax25,
 | 
			
		||||
int patty_ax25_close(int server,
 | 
			
		||||
                     int socket);
 | 
			
		||||
 | 
			
		||||
/*int patty_ax25_next_event(patty_ax25 *ax25,
 | 
			
		||||
    patty_ax25_event *ev);*/
 | 
			
		||||
 | 
			
		||||
ssize_t patty_ax25_sendto(patty_ax25 *ax25,
 | 
			
		||||
ssize_t patty_ax25_sendto(int server,
 | 
			
		||||
                          int socket,
 | 
			
		||||
                          const void *buf,
 | 
			
		||||
                          size_t len,
 | 
			
		||||
                          patty_ax25_addr *addr);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_recvfrom(patty_ax25 *ax25,
 | 
			
		||||
int patty_ax25_recvfrom(int server,
 | 
			
		||||
                        int socket,
 | 
			
		||||
                        void *buf,
 | 
			
		||||
                        size_t len,
 | 
			
		||||
                        patty_ax25_addr *addr);
 | 
			
		||||
 | 
			
		||||
ssize_t patty_ax25_read(patty_ax25 *ax25,
 | 
			
		||||
                        int socket,
 | 
			
		||||
                        void *buf,
 | 
			
		||||
                        size_t len);
 | 
			
		||||
 | 
			
		||||
ssize_t patty_ax25_write(patty_ax25 *ax25,
 | 
			
		||||
                         int socket,
 | 
			
		||||
                         const void *buf,
 | 
			
		||||
                         size_t len);
 | 
			
		||||
 | 
			
		||||
#endif /* _PATTY_AX25_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								include/patty/ax25/client.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/patty/ax25/client.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
#ifndef _PATTY_AX25_CLIENT_H
 | 
			
		||||
#define _PATTY_AX25_CLIENT_H
 | 
			
		||||
 | 
			
		||||
enum patty_ax25_client_call {
 | 
			
		||||
    PATTY_AX25_CLIENT_UNKNOWN,
 | 
			
		||||
    PATTY_AX25_CLIENT_SOCKET,
 | 
			
		||||
    PATTY_AX25_CLIENT_BIND,
 | 
			
		||||
    PATTY_AX25_CLIENT_LISTEN,
 | 
			
		||||
    PATTY_AX25_CLIENT_ACCEPT,
 | 
			
		||||
    PATTY_AX25_CLIENT_CONNECT,
 | 
			
		||||
    PATTY_AX25_CLIENT_CLOSE,
 | 
			
		||||
    PATTY_AX25_CLIENT_SENDTO,
 | 
			
		||||
    PATTY_AX25_CLIENT_RECVFROM
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ssize_t patty_ax25_client_send(int fd,
 | 
			
		||||
                               enum patty_ax25_client_call call,
 | 
			
		||||
                               void *data,
 | 
			
		||||
                               size_t len);
 | 
			
		||||
 | 
			
		||||
#endif /* _PATTY_AX25_CLIENT_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -48,13 +48,17 @@ int patty_ax25_if_add_addr(patty_ax25_if *iface,
 | 
			
		|||
int patty_ax25_if_delete_addr(patty_ax25_if *iface,
 | 
			
		||||
    const char *callsign, uint8_t ssid);
 | 
			
		||||
 | 
			
		||||
patty_ax25_if *patty_ax25_get_if(patty_ax25 *ax25, const char *name);
 | 
			
		||||
patty_ax25_if *patty_ax25_get_if(patty_ax25_server *server,
 | 
			
		||||
                                 const char *name);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_if_each(patty_ax25 *ax25,
 | 
			
		||||
    int (*callback)(patty_ax25_if *, void *), void *ctx);
 | 
			
		||||
int patty_ax25_if_each(patty_ax25_server *server,
 | 
			
		||||
                       int (*callback)(patty_ax25_if *, void *),
 | 
			
		||||
                       void *ctx);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_add_if(patty_ax25 *ax25, patty_ax25_if *iface);
 | 
			
		||||
int patty_ax25_add_if(patty_ax25_server *server,
 | 
			
		||||
                      patty_ax25_if *iface);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_delete_if(patty_ax25 *ax25, patty_ax25_if *iface);
 | 
			
		||||
int patty_ax25_delete_if(patty_ax25_server *server,
 | 
			
		||||
                         patty_ax25_if *iface);
 | 
			
		||||
 | 
			
		||||
#endif /* _PATTY_AX25_IF_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,33 +0,0 @@
 | 
			
		|||
#ifndef _PATTY_AX25_MUX_H
 | 
			
		||||
#define _PATTY_AX25_MUX_H
 | 
			
		||||
 | 
			
		||||
enum patty_ax25_mux_data_type {
 | 
			
		||||
    PATTY_AX25_MUX_VOID,
 | 
			
		||||
    PATTY_AX25_MUX_INT,
 | 
			
		||||
    PATTY_AX25_MUX_SSIZE_T,
 | 
			
		||||
    PATTY_AX25_MUX_ADDR
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum patty_ax25_mux_request_type {
 | 
			
		||||
    PATTY_AX25_MUX_UNKNOWN,
 | 
			
		||||
    PATTY_AX25_MUX_SOCKET,
 | 
			
		||||
    PATTY_AX25_MUX_BIND,
 | 
			
		||||
    PATTY_AX25_MUX_LISTEN,
 | 
			
		||||
    PATTY_AX25_MUX_ACCEPT,
 | 
			
		||||
    PATTY_AX25_MUX_CONNECT,
 | 
			
		||||
    PATTY_AX25_MUX_CLOSE,
 | 
			
		||||
    PATTY_AX25_MUX_SENDTO,
 | 
			
		||||
    PATTY_AX25_MUX_RECVFROM
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ssize_t patty_ax25_mux_send(int fd,
 | 
			
		||||
                            enum patty_ax25_mux_request_type type,
 | 
			
		||||
                            void *data,
 | 
			
		||||
                            size_t len);
 | 
			
		||||
 | 
			
		||||
ssize_t patty_ax25_mux_recv(int fd,
 | 
			
		||||
                            enum patty_ax25_mux_response_type *type,
 | 
			
		||||
                            void *data,
 | 
			
		||||
                            size_t len);
 | 
			
		||||
 | 
			
		||||
#endif /* _PATTY_AX25_MUX_H */
 | 
			
		||||
							
								
								
									
										24
									
								
								include/patty/ax25/server.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/patty/ax25/server.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#ifndef _PATTY_AX25_SERVER_H
 | 
			
		||||
#define _PATTY_AX25_SERVER_H
 | 
			
		||||
 | 
			
		||||
typedef struct _patty_ax25_server {
 | 
			
		||||
    patty_list *ifaces;
 | 
			
		||||
 | 
			
		||||
    patty_dict *socks,
 | 
			
		||||
               *socks_by_addrpair;
 | 
			
		||||
 | 
			
		||||
    int fd,
 | 
			
		||||
        fd_max;
 | 
			
		||||
 | 
			
		||||
    fd_set fds,
 | 
			
		||||
           fds_r,
 | 
			
		||||
           fds_w;
 | 
			
		||||
} patty_ax25_server;
 | 
			
		||||
 | 
			
		||||
int patty_ax25_server_init(patty_ax25_server *server);
 | 
			
		||||
 | 
			
		||||
void patty_ax25_server_stop(patty_ax25_server *server);
 | 
			
		||||
 | 
			
		||||
int patty_ax25_server_run(patty_ax25_server *server);
 | 
			
		||||
 | 
			
		||||
#endif /* _PATTY_AX25_SERVER_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -8,12 +8,12 @@ CFLAGS		= $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
 | 
			
		|||
LDFLAGS		=
 | 
			
		||||
 | 
			
		||||
HEADERS		= kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h \
 | 
			
		||||
		  ax25/frame.h list.h hash.h dict.h
 | 
			
		||||
		  ax25/frame.h ax25/server.h list.h hash.h dict.h
 | 
			
		||||
 | 
			
		||||
OBJS		= kiss.o ax25.o if.o frame.o \
 | 
			
		||||
		  list.o hash.o dict.o
 | 
			
		||||
		  server.o list.o hash.o dict.o
 | 
			
		||||
 | 
			
		||||
EXAMPLES	= iflist decode ptmx
 | 
			
		||||
EXAMPLES	= decode ptmx
 | 
			
		||||
 | 
			
		||||
HEADERS_BUILD	= $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/, $(HEADERS))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										292
									
								
								src/ax25.c
									
										
									
									
									
								
							
							
						
						
									
										292
									
								
								src/ax25.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,184 +5,17 @@
 | 
			
		|||
 | 
			
		||||
#include <patty/ax25.h>
 | 
			
		||||
 | 
			
		||||
int patty_ax25_init(patty_ax25 *ax25) {
 | 
			
		||||
    memset(ax25, '\0', sizeof(*ax25));
 | 
			
		||||
 | 
			
		||||
    if ((ax25->ifaces = patty_list_new()) == NULL) {
 | 
			
		||||
        goto error_list_new_ifaces;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((ax25->socks = patty_dict_new()) == NULL) {
 | 
			
		||||
        goto error_dict_new_socks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((ax25->socks_by_addrpair = patty_dict_new()) == NULL) {
 | 
			
		||||
        goto error_dict_new_socks_by_addrpair;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error_dict_new_socks_by_addrpair:
 | 
			
		||||
    patty_dict_destroy(ax25->socks);
 | 
			
		||||
 | 
			
		||||
error_dict_new_socks:
 | 
			
		||||
    patty_list_destroy(ax25->ifaces);
 | 
			
		||||
 | 
			
		||||
error_list_new_ifaces:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int destroy_if(patty_ax25_if *iface, void *ctx) {
 | 
			
		||||
    patty_ax25_if_destroy(iface);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void patty_ax25_stop(patty_ax25 *ax25) {
 | 
			
		||||
    patty_dict_destroy(ax25->socks_by_addrpair);
 | 
			
		||||
    patty_dict_destroy(ax25->socks);
 | 
			
		||||
 | 
			
		||||
    patty_ax25_if_each(ax25, destroy_if, NULL);
 | 
			
		||||
    patty_list_destroy(ax25->ifaces);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static patty_ax25_sock *sock_by_fd(patty_ax25 *ax25, int fd) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = patty_dict_get(ax25->socks, &fd, sizeof(fd))) == NULL) {
 | 
			
		||||
        errno = EBADF;
 | 
			
		||||
 | 
			
		||||
        goto error_dict_get;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock;
 | 
			
		||||
 | 
			
		||||
error_dict_get:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_init(uint32_t *hash) {
 | 
			
		||||
    *hash = 0xffffffdf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_byte(uint32_t *hash, uint8_t c) {
 | 
			
		||||
    *hash += c;
 | 
			
		||||
    *hash += (*hash << 10);
 | 
			
		||||
    *hash ^= (*hash >>  6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_addr(uint32_t *hash, patty_ax25_addr *addr) {
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i=0; i<PATTY_AX25_CALLSIGN_LEN; i++) {
 | 
			
		||||
        hash_byte(hash, addr->callsign[i] >> 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hash_byte(hash, PATTY_AX25_ADDRESS_SSID_NUMBER(addr->ssid));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_end(uint32_t *hash) {
 | 
			
		||||
    *hash += (*hash <<  3);
 | 
			
		||||
    *hash ^= (*hash >> 11);
 | 
			
		||||
    *hash += (*hash << 15);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t hash_addrpair(patty_ax25_addr *local,
 | 
			
		||||
                              patty_ax25_addr *remote) {
 | 
			
		||||
    uint32_t hash;
 | 
			
		||||
 | 
			
		||||
    hash_init(&hash);
 | 
			
		||||
 | 
			
		||||
    hash_addr(&hash, local);
 | 
			
		||||
    hash_addr(&hash, remote);
 | 
			
		||||
 | 
			
		||||
    hash_end(&hash);
 | 
			
		||||
 | 
			
		||||
    return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static patty_ax25_sock *sock_get_fd(patty_ax25 *ax25,
 | 
			
		||||
                                    int fd) {
 | 
			
		||||
    return patty_dict_get(ax25->socks,
 | 
			
		||||
                          NULL + fd,
 | 
			
		||||
                          sizeof(fd));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static patty_ax25_sock *sock_get_addrpair(patty_ax25 *ax25,
 | 
			
		||||
                                          patty_ax25_addr *local,
 | 
			
		||||
                                          patty_ax25_addr *remote) {
 | 
			
		||||
    patty_dict_slot *slot;
 | 
			
		||||
 | 
			
		||||
    uint32_t hash = hash_addrpair(local, remote);
 | 
			
		||||
 | 
			
		||||
    if ((slot = patty_dict_slot_find(ax25->socks_by_addrpair, hash)) == NULL) {
 | 
			
		||||
        errno = EBADF;
 | 
			
		||||
 | 
			
		||||
        goto error_dict_slot_find;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (patty_ax25_sock *)slot->value;
 | 
			
		||||
 | 
			
		||||
error_dict_slot_find:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sock_save(patty_ax25 *ax25, patty_ax25_sock *sock) {
 | 
			
		||||
    uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
 | 
			
		||||
 | 
			
		||||
    if (patty_dict_set(ax25->socks,
 | 
			
		||||
                       NULL + sock->fd,
 | 
			
		||||
                       sizeof(sock->fd),
 | 
			
		||||
                       sock) == NULL) {
 | 
			
		||||
        goto error_dict_set;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_dict_set_with_hash(ax25->socks_by_addrpair,
 | 
			
		||||
                                 NULL + sock->fd,
 | 
			
		||||
                                 sizeof(sock->fd),
 | 
			
		||||
                                 sock,
 | 
			
		||||
                                 hash) == NULL) {
 | 
			
		||||
        goto error_dict_set;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock->fd;
 | 
			
		||||
 | 
			
		||||
error_dict_set:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sock_init(patty_ax25_sock *sock) {
 | 
			
		||||
    memset(sock, '\0', sizeof(*sock));
 | 
			
		||||
 | 
			
		||||
    sock->status   = PATTY_AX25_SOCK_OPEN;
 | 
			
		||||
    sock->mode     = PATTY_AX25_SOCK_DM;
 | 
			
		||||
    sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
 | 
			
		||||
    sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_socket(patty_ax25 *ax25) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = malloc(sizeof(*sock))) == NULL) {
 | 
			
		||||
        goto error_malloc_sock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sock_init(sock);
 | 
			
		||||
 | 
			
		||||
    sock->fd = ax25->fd++;
 | 
			
		||||
 | 
			
		||||
    if (sock_save(ax25, sock) < 0) {
 | 
			
		||||
        goto error_sock_save;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock->fd;
 | 
			
		||||
 | 
			
		||||
error_sock_save:
 | 
			
		||||
    free(sock);
 | 
			
		||||
 | 
			
		||||
error_malloc_sock:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
enum remote_call {
 | 
			
		||||
    PATTY_AX25_UNKNOWN,
 | 
			
		||||
    PATTY_AX25_SOCKET,
 | 
			
		||||
    PATTY_AX25_BIND,
 | 
			
		||||
    PATTY_AX25_LISTEN,
 | 
			
		||||
    PATTY_AX25_ACCEPT,
 | 
			
		||||
    PATTY_AX25_CONNECT,
 | 
			
		||||
    PATTY_AX25_CLOSE,
 | 
			
		||||
    PATTY_AX25_SENDTO,
 | 
			
		||||
    PATTY_AX25_RECVFROM
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int patty_ax25_pton(const char *callsign,
 | 
			
		||||
                    uint8_t ssid,
 | 
			
		||||
| 
						 | 
				
			
			@ -269,106 +102,3 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
 | 
			
		|||
error_invalid_args:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_open(patty_ax25 *ax25, const char *ifname) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = malloc(sizeof(*sock))) == NULL) {
 | 
			
		||||
        goto error_malloc_sock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sock_init(sock);
 | 
			
		||||
 | 
			
		||||
    if ((sock->iface = patty_ax25_get_if(ax25, ifname)) == NULL) {
 | 
			
		||||
        goto error_get_if;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock_save(ax25, sock);
 | 
			
		||||
 | 
			
		||||
error_get_if:
 | 
			
		||||
    free(sock);
 | 
			
		||||
 | 
			
		||||
error_malloc_sock:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_bind(patty_ax25 *ax25,
 | 
			
		||||
                    int socket,
 | 
			
		||||
                    patty_ax25_addr *addr) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = sock_get_fd(ax25, socket)) == NULL) {
 | 
			
		||||
        goto error_sock_get_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * If there is already a local address associated with this socket, then
 | 
			
		||||
     * that's a problem.
 | 
			
		||||
     */
 | 
			
		||||
    if (sock->local.callsign[0] != '\0') {
 | 
			
		||||
        errno = EADDRINUSE;
 | 
			
		||||
 | 
			
		||||
        goto error_exists;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(&sock->local, addr, sizeof(*addr));
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error_exists:
 | 
			
		||||
error_sock_get_fd:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_listen(patty_ax25 *ax25,
 | 
			
		||||
                      int socket) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = sock_get_fd(ax25, socket)) == NULL) {
 | 
			
		||||
        errno = EBADF;
 | 
			
		||||
 | 
			
		||||
        goto error_sock_get_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sock->local.callsign[0] == '\0') {
 | 
			
		||||
        errno = EINVAL;
 | 
			
		||||
 | 
			
		||||
        goto error_invalid_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    errno = ENOSYS;
 | 
			
		||||
 | 
			
		||||
error_invalid_fd:
 | 
			
		||||
error_sock_get_fd:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_connect(patty_ax25 *ax25,
 | 
			
		||||
                       int socket,
 | 
			
		||||
                       patty_ax25_addr *addr) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = sock_get_fd(ax25, socket)) == NULL) {
 | 
			
		||||
        goto error_sock_get_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sock->remote.callsign[0] != '\0') {
 | 
			
		||||
        errno = EEXIST;
 | 
			
		||||
 | 
			
		||||
        goto error_exists;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(&sock->remote, addr, sizeof(*addr));
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error_exists:
 | 
			
		||||
error_sock_get_fd:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_accept(patty_ax25 *ax25, int socket) {
 | 
			
		||||
    errno = ENOSYS;
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										39
									
								
								src/if.c
									
										
									
									
									
								
							
							
						
						
									
										39
									
								
								src/if.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -221,11 +221,12 @@ error_ntop:
 | 
			
		|||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
patty_ax25_if *patty_ax25_get_if(patty_ax25 *ax25, const char *name) {
 | 
			
		||||
patty_ax25_if *patty_ax25_get_if(patty_ax25_server *server,
 | 
			
		||||
                                 const char *name) {
 | 
			
		||||
    patty_list_iterator *iter;
 | 
			
		||||
    patty_ax25_if *iface;
 | 
			
		||||
 | 
			
		||||
    if ((iter = patty_list_start(ax25->ifaces)) == NULL) {
 | 
			
		||||
    if ((iter = patty_list_start(server->ifaces)) == NULL) {
 | 
			
		||||
        goto error_list_start;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -243,11 +244,13 @@ error_list_start:
 | 
			
		|||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_if_each(patty_ax25 *ax25, int (*callback)(patty_ax25_if *, void *), void *ctx) {
 | 
			
		||||
int patty_ax25_if_each(patty_ax25_server *server,
 | 
			
		||||
                       int (*callback)(patty_ax25_if *, void *),
 | 
			
		||||
                       void *ctx) {
 | 
			
		||||
    patty_list_iterator *iter;
 | 
			
		||||
    patty_ax25_if *iface;
 | 
			
		||||
 | 
			
		||||
    if ((iter = patty_list_start(ax25->ifaces)) == NULL) {
 | 
			
		||||
    if ((iter = patty_list_start(server->ifaces)) == NULL) {
 | 
			
		||||
        goto error_list_start;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -268,22 +271,23 @@ error_list_start:
 | 
			
		|||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_add_if(patty_ax25 *ax25, patty_ax25_if *iface) {
 | 
			
		||||
int patty_ax25_add_if(patty_ax25_server *server,
 | 
			
		||||
                      patty_ax25_if *iface) {
 | 
			
		||||
    int fd;
 | 
			
		||||
 | 
			
		||||
    if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
 | 
			
		||||
        FD_SET(fd, &ax25->fds);
 | 
			
		||||
        FD_SET(fd, &server->fds);
 | 
			
		||||
 | 
			
		||||
        if (ax25->fdmax < fd + 1) {
 | 
			
		||||
            ax25->fdmax = fd + 1;
 | 
			
		||||
        if (server->fd_max < fd + 1) {
 | 
			
		||||
            server->fd_max = fd + 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_dict_set(ax25->socks, NULL + fd, sizeof(fd), iface) == NULL) {
 | 
			
		||||
    if (patty_dict_set(server->socks, NULL + fd, sizeof(fd), iface) == NULL) {
 | 
			
		||||
        goto error_dict_set;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_list_append(ax25->ifaces, iface) == NULL) {
 | 
			
		||||
    if (patty_list_append(server->ifaces, iface) == NULL) {
 | 
			
		||||
        goto error_list_append;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -294,14 +298,15 @@ error_dict_set:
 | 
			
		|||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int patty_ax25_delete_if(patty_ax25 *ax25, patty_ax25_if *iface) {
 | 
			
		||||
    patty_list_item *item = ax25->ifaces->first;
 | 
			
		||||
int patty_ax25_delete_if(patty_ax25_server *server,
 | 
			
		||||
                         patty_ax25_if *iface) {
 | 
			
		||||
    patty_list_item *item = server->ifaces->first;
 | 
			
		||||
 | 
			
		||||
    int fd, i = 0;
 | 
			
		||||
 | 
			
		||||
    while (item) {
 | 
			
		||||
        if (item->value == iface) {
 | 
			
		||||
            if (patty_list_splice(ax25->ifaces, i) == NULL) {
 | 
			
		||||
            if (patty_list_splice(server->ifaces, i) == NULL) {
 | 
			
		||||
                goto error_list_splice;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -313,13 +318,13 @@ int patty_ax25_delete_if(patty_ax25 *ax25, patty_ax25_if *iface) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
 | 
			
		||||
        FD_CLR(fd, &ax25->fds);
 | 
			
		||||
        FD_CLR(fd, &server->fds);
 | 
			
		||||
 | 
			
		||||
        if (ax25->fdmax == fd) {
 | 
			
		||||
            ax25->fdmax--;
 | 
			
		||||
        if (server->fd_max == fd) {
 | 
			
		||||
            server->fd_max--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (patty_dict_delete(ax25->socks, NULL + fd, sizeof(fd)) == NULL) {
 | 
			
		||||
        if (patty_dict_delete(server->socks, NULL + fd, sizeof(fd)) == NULL) {
 | 
			
		||||
            goto error_dict_delete;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										74
									
								
								src/iflist.c
									
										
									
									
									
								
							
							
						
						
									
										74
									
								
								src/iflist.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,74 +0,0 @@
 | 
			
		|||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <patty/kiss.h>
 | 
			
		||||
#include <patty/ax25.h>
 | 
			
		||||
 | 
			
		||||
static void usage(int argc, char **argv, const char *message, ...) {
 | 
			
		||||
    if (message) {
 | 
			
		||||
        va_list args;
 | 
			
		||||
 | 
			
		||||
        va_start(args, message);
 | 
			
		||||
        vfprintf(stderr, message, args);
 | 
			
		||||
         fprintf(stderr, "\n");
 | 
			
		||||
        va_end(args);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fprintf(stderr, "usage: %s device\n", argv[0]);
 | 
			
		||||
 | 
			
		||||
    exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int addr_callback(char *callsign, uint8_t ssid, void *ctx) {
 | 
			
		||||
    return printf("    %s/%d\n", callsign, ssid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int iface_callback(patty_ax25_if *iface, void *ctx) {
 | 
			
		||||
    printf("%s:\n", iface->name);
 | 
			
		||||
 | 
			
		||||
    return patty_ax25_if_each_addr(iface, addr_callback, ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
    patty_ax25 ax25;
 | 
			
		||||
    patty_ax25_if *iface;
 | 
			
		||||
 | 
			
		||||
    if (argc < 2) {
 | 
			
		||||
        usage(argc, argv, "No TNC device provided");
 | 
			
		||||
    } else if (argc > 2) {
 | 
			
		||||
        usage(argc, argv, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_ax25_init(&ax25) < 0) {
 | 
			
		||||
        perror("Unable to initialize AX.25 stack");
 | 
			
		||||
 | 
			
		||||
        exit(127);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((iface = patty_ax25_if_create(PATTY_AX25_IF_KISS_TNC, argv[1])) == NULL) {
 | 
			
		||||
        perror("Unable to create interface");
 | 
			
		||||
 | 
			
		||||
        exit(127);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_ax25_if_add_addr(iface, "WX3RKR", 0) < 0) {
 | 
			
		||||
        perror("Unable to add address");
 | 
			
		||||
 | 
			
		||||
        exit(127);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_ax25_add_if(&ax25, iface) < 0) {
 | 
			
		||||
        perror("Unable to add interface");
 | 
			
		||||
 | 
			
		||||
        exit(127);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    patty_ax25_if_each(&ax25, iface_callback, NULL);
 | 
			
		||||
 | 
			
		||||
    patty_ax25_stop(&ax25);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										386
									
								
								src/server.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								src/server.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,386 @@
 | 
			
		|||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <patty/ax25.h>
 | 
			
		||||
 | 
			
		||||
int patty_ax25_server_init(patty_ax25_server *server) {
 | 
			
		||||
    memset(server, '\0', sizeof(*server));
 | 
			
		||||
 | 
			
		||||
    if ((server->ifaces = patty_list_new()) == NULL) {
 | 
			
		||||
        goto error_list_new_ifaces;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((server->socks = patty_dict_new()) == NULL) {
 | 
			
		||||
        goto error_dict_new_socks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((server->socks_by_addrpair = patty_dict_new()) == NULL) {
 | 
			
		||||
        goto error_dict_new_socks_by_addrpair;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error_dict_new_socks_by_addrpair:
 | 
			
		||||
    patty_dict_destroy(server->socks);
 | 
			
		||||
 | 
			
		||||
error_dict_new_socks:
 | 
			
		||||
    patty_list_destroy(server->ifaces);
 | 
			
		||||
 | 
			
		||||
error_list_new_ifaces:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int destroy_if(patty_ax25_if *iface, void *ctx) {
 | 
			
		||||
    patty_ax25_if_destroy(iface);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void patty_ax25_server_stop(patty_ax25_server *server) {
 | 
			
		||||
    patty_dict_destroy(server->socks_by_addrpair);
 | 
			
		||||
    patty_dict_destroy(server->socks);
 | 
			
		||||
 | 
			
		||||
    patty_ax25_if_each(server, destroy_if, NULL);
 | 
			
		||||
    patty_list_destroy(server->ifaces);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sock_init(patty_ax25_sock *sock) {
 | 
			
		||||
    memset(sock, '\0', sizeof(*sock));
 | 
			
		||||
 | 
			
		||||
    sock->status   = PATTY_AX25_SOCK_OPEN;
 | 
			
		||||
    sock->mode     = PATTY_AX25_SOCK_DM;
 | 
			
		||||
    sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
 | 
			
		||||
    sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_init(uint32_t *hash) {
 | 
			
		||||
    *hash = 0xffffffdf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_byte(uint32_t *hash, uint8_t c) {
 | 
			
		||||
    *hash += c;
 | 
			
		||||
    *hash += (*hash << 10);
 | 
			
		||||
    *hash ^= (*hash >>  6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_addr(uint32_t *hash, patty_ax25_addr *addr) {
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i=0; i<PATTY_AX25_CALLSIGN_LEN; i++) {
 | 
			
		||||
        hash_byte(hash, addr->callsign[i] >> 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hash_byte(hash, PATTY_AX25_ADDRESS_SSID_NUMBER(addr->ssid));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void hash_end(uint32_t *hash) {
 | 
			
		||||
    *hash += (*hash <<  3);
 | 
			
		||||
    *hash ^= (*hash >> 11);
 | 
			
		||||
    *hash += (*hash << 15);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t hash_addrpair(patty_ax25_addr *local,
 | 
			
		||||
                              patty_ax25_addr *remote) {
 | 
			
		||||
    uint32_t hash;
 | 
			
		||||
 | 
			
		||||
    hash_init(&hash);
 | 
			
		||||
 | 
			
		||||
    hash_addr(&hash, local);
 | 
			
		||||
    hash_addr(&hash, remote);
 | 
			
		||||
 | 
			
		||||
    hash_end(&hash);
 | 
			
		||||
 | 
			
		||||
    return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sock_save(patty_ax25_server *server, patty_ax25_sock *sock) {
 | 
			
		||||
    uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
 | 
			
		||||
 | 
			
		||||
    if (patty_dict_set(server->socks,
 | 
			
		||||
                       NULL + sock->fd,
 | 
			
		||||
                       sizeof(sock->fd),
 | 
			
		||||
                       sock) == NULL) {
 | 
			
		||||
        goto error_dict_set;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (patty_dict_set_with_hash(server->socks_by_addrpair,
 | 
			
		||||
                                 NULL + sock->fd,
 | 
			
		||||
                                 sizeof(sock->fd),
 | 
			
		||||
                                 sock,
 | 
			
		||||
                                 hash) == NULL) {
 | 
			
		||||
        goto error_dict_set;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock->fd;
 | 
			
		||||
 | 
			
		||||
error_dict_set:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_open(patty_ax25_server *server, const char *ifname) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = malloc(sizeof(*sock))) == NULL) {
 | 
			
		||||
        goto error_malloc_sock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sock_init(sock);
 | 
			
		||||
 | 
			
		||||
    if ((sock->iface = patty_ax25_get_if(server, ifname)) == NULL) {
 | 
			
		||||
        goto error_get_if;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock_save(server, sock);
 | 
			
		||||
 | 
			
		||||
error_get_if:
 | 
			
		||||
    free(sock);
 | 
			
		||||
 | 
			
		||||
error_malloc_sock:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static patty_ax25_sock *sock_by_fd(patty_ax25_server *server, int fd) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = patty_dict_get(server->socks, &fd, sizeof(fd))) == NULL) {
 | 
			
		||||
        errno = EBADF;
 | 
			
		||||
 | 
			
		||||
        goto error_dict_get;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock;
 | 
			
		||||
 | 
			
		||||
error_dict_get:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static patty_ax25_sock *sock_get_fd(patty_ax25_server *server,
 | 
			
		||||
                                    int fd) {
 | 
			
		||||
    return patty_dict_get(server->socks,
 | 
			
		||||
                          NULL + fd,
 | 
			
		||||
                          sizeof(fd));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static patty_ax25_sock *sock_get_addrpair(patty_ax25_server *server,
 | 
			
		||||
                                          patty_ax25_addr *local,
 | 
			
		||||
                                          patty_ax25_addr *remote) {
 | 
			
		||||
    patty_dict_slot *slot;
 | 
			
		||||
 | 
			
		||||
    uint32_t hash = hash_addrpair(local, remote);
 | 
			
		||||
 | 
			
		||||
    if ((slot = patty_dict_slot_find(server->socks_by_addrpair, hash)) == NULL) {
 | 
			
		||||
        errno = EBADF;
 | 
			
		||||
 | 
			
		||||
        goto error_dict_slot_find;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (patty_ax25_sock *)slot->value;
 | 
			
		||||
 | 
			
		||||
error_dict_slot_find:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_socket_pty(patty_ax25_server *server,
 | 
			
		||||
                             patty_ax25_sock *sock,
 | 
			
		||||
                             int client) {
 | 
			
		||||
    int fd;
 | 
			
		||||
    char name[64];
 | 
			
		||||
    size_t len;
 | 
			
		||||
 | 
			
		||||
    if ((fd = open("/dev/ptmx", O_RDWR)) < 0) {
 | 
			
		||||
        goto error_open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (grantpt(fd) < 0) {
 | 
			
		||||
        goto error_grantpt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (unlockpt(fd) < 0) {
 | 
			
		||||
        goto error_unlockpt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ptsname_r(fd, name, sizeof(name)) < 0) {
 | 
			
		||||
        goto error_ptsname_r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    len = strnlen(name, sizeof(name) - 1);
 | 
			
		||||
 | 
			
		||||
    if (write(client, name, sizeof(len)) < 0) {
 | 
			
		||||
        goto error_write;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (write(client, name, len) < 0) {
 | 
			
		||||
        goto error_write;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock->fd = fd;
 | 
			
		||||
 | 
			
		||||
error_write:
 | 
			
		||||
error_ptsname_r:
 | 
			
		||||
error_unlockpt:
 | 
			
		||||
error_grantpt:
 | 
			
		||||
    close(fd);
 | 
			
		||||
 | 
			
		||||
error_open:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_socket_unix(patty_ax25_server *server,
 | 
			
		||||
                              patty_ax25_sock *sock,
 | 
			
		||||
                              int client) {
 | 
			
		||||
    int fd;
 | 
			
		||||
    char name[256];
 | 
			
		||||
    size_t len;
 | 
			
		||||
 | 
			
		||||
    struct sockaddr_un addr;
 | 
			
		||||
 | 
			
		||||
    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
 | 
			
		||||
        goto error_socket;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (snprintf(name, sizeof(name), "/var/run/patty/%d.sock", fd) < 0) {
 | 
			
		||||
        goto error_snprintf_name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    len = strnlen(name, sizeof(name));
 | 
			
		||||
 | 
			
		||||
    addr.sun_family = AF_UNIX;
 | 
			
		||||
 | 
			
		||||
    memset(&addr, 0, sizeof(addr));
 | 
			
		||||
    strncpy(addr.sun_path, name, sizeof(addr.sun_path));
 | 
			
		||||
 | 
			
		||||
    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 | 
			
		||||
        goto error_bind;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (write(client, &len, sizeof(len)) < 0) {
 | 
			
		||||
        goto error_write;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (write(client, name, len) < 0) {
 | 
			
		||||
        goto error_write;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock->fd = fd;
 | 
			
		||||
 | 
			
		||||
error_write:
 | 
			
		||||
error_bind:
 | 
			
		||||
error_snprintf_name:
 | 
			
		||||
    close(fd);
 | 
			
		||||
 | 
			
		||||
error_socket:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_socket(patty_ax25_server *server,
 | 
			
		||||
                         int client,
 | 
			
		||||
                         int sockopts) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = malloc(sizeof(*sock))) == NULL) {
 | 
			
		||||
        goto error_malloc_sock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sock_init(sock);
 | 
			
		||||
 | 
			
		||||
    if (sockopts & PATTY_AX25_SOCK_PTY) {
 | 
			
		||||
        if (server_socket_pty(server, sock, client) < 0) {
 | 
			
		||||
            goto error;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sock->fd;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
    free(sock);
 | 
			
		||||
 | 
			
		||||
error_malloc_sock:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_bind(patty_ax25_server *server,
 | 
			
		||||
                       int socket,
 | 
			
		||||
                       patty_ax25_addr *addr) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = sock_get_fd(server, socket)) == NULL) {
 | 
			
		||||
        goto error_sock_get_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * If there is already a local address associated with this socket, then
 | 
			
		||||
     * that's a problem.
 | 
			
		||||
     */
 | 
			
		||||
    if (sock->local.callsign[0] != '\0') {
 | 
			
		||||
        errno = EADDRINUSE;
 | 
			
		||||
 | 
			
		||||
        goto error_exists;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(&sock->local, addr, sizeof(*addr));
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error_exists:
 | 
			
		||||
error_sock_get_fd:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_listen(patty_ax25_server *server,
 | 
			
		||||
                         int socket) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = sock_get_fd(server, socket)) == NULL) {
 | 
			
		||||
        errno = EBADF;
 | 
			
		||||
 | 
			
		||||
        goto error_sock_get_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sock->local.callsign[0] == '\0') {
 | 
			
		||||
        errno = EINVAL;
 | 
			
		||||
 | 
			
		||||
        goto error_invalid_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    errno = ENOSYS;
 | 
			
		||||
 | 
			
		||||
error_invalid_fd:
 | 
			
		||||
error_sock_get_fd:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_connect(patty_ax25_server *server,
 | 
			
		||||
                          int socket,
 | 
			
		||||
                          patty_ax25_addr *addr) {
 | 
			
		||||
    patty_ax25_sock *sock;
 | 
			
		||||
 | 
			
		||||
    if ((sock = sock_get_fd(server, socket)) == NULL) {
 | 
			
		||||
        goto error_sock_get_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sock->remote.callsign[0] != '\0') {
 | 
			
		||||
        errno = EEXIST;
 | 
			
		||||
 | 
			
		||||
        goto error_exists;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(&sock->remote, addr, sizeof(*addr));
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error_exists:
 | 
			
		||||
error_sock_get_fd:
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int server_accept(patty_ax25_server *server, int socket) {
 | 
			
		||||
    errno = ENOSYS;
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue