#include #include #include #include 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_list_new()) == NULL) { goto error_list_new_socks; } if ((ax25->fd_lookup = patty_dict_new()) == NULL) { goto error_dict_new_fd_lookup; } ax25->fd = 0; return 0; error_dict_new_fd_lookup: patty_list_destroy(ax25->socks); error_list_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->fd_lookup); patty_list_destroy(ax25->socks); patty_ax25_each_if(ax25, destroy_if, NULL); patty_list_destroy(ax25->ifaces); } static void *fd_lookup(patty_ax25 *ax25, int fd) { void *obj; if ((obj = patty_dict_get(ax25->fd_lookup, &fd, sizeof(fd))) == NULL) { errno = EBADF; goto error_dict_get; } return obj; error_dict_get: return NULL; } static int fd_store(patty_ax25 *ax25, patty_ax25_sock *sock) { if (patty_dict_set(ax25->fd_lookup, &ax25->fd, sizeof(ax25->fd), sock) == NULL) { goto error_dict_set; } return ax25->fd++; error_dict_set: return -1; } int patty_ax25_socket(patty_ax25 *ax25) { patty_ax25_sock *sock; int fd; if ((sock = malloc(sizeof(*sock))) == NULL) { goto error_malloc_sock; } memset(sock, '\0', sizeof(*sock)); sock->status = PATTY_AX25_SOCK_OPEN; if ((fd = fd_store(ax25, sock)) < 0) { goto error_fd_store; } return fd; error_fd_store: free(sock); error_malloc_sock: 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; } memset(sock, '\0', sizeof(*sock)); if ((sock->iface = patty_ax25_get_if(ax25, ifname)) == NULL) { goto error_get_if; } return fd_store(ax25, sock); error_get_if: free(sock); error_malloc_sock: return -1; } int patty_ax25_bind(patty_ax25 *ax25, int socket, const char *callsign, int ssid) { patty_ax25_sock *sock; if ((sock = fd_lookup(ax25, socket)) == NULL) { goto error_fd_lookup; } /* * If there is already a local address associated with this socket, then * that's a problem. */ if (sock->local != NULL) { errno = EEXIST; goto error_exists; } if ((sock->local = patty_ax25_address_create(callsign, ssid)) == NULL) { goto error_address_create; } return 0; error_address_create: error_exists: error_fd_lookup: return -1; } int patty_ax25_listen(patty_ax25 *ax25, int socket, const char *callsign, int ssid) { /* * Stub */ return patty_ax25_bind(ax25, socket, callsign, ssid); } int patty_ax25_connect(patty_ax25 *ax25, int socket, const char *callsign, int ssid) { patty_ax25_sock *sock; if ((sock = fd_lookup(ax25, socket)) == NULL) { goto error_fd_lookup; } if (sock->remote != NULL) { errno = EEXIST; goto error_exists; } if ((sock->remote = patty_ax25_address_create(callsign, ssid)) == NULL) { goto error_address_create; } return 0; error_address_create: error_exists: error_fd_lookup: return -1; }