Implement support for sending frames with SOCK_RAW
Changes:
    * When associating a promiscuous socket with an interface, rather
      than creating a patty_kiss_tnc object, simply store the socket
      file descriptor and use patty_kiss_frame_send() to send incoming
      or outgoing frames for that interface to the promiscuous socket
    * Add special initialization code in src/sock.c for SOCK_RAW; don't
      allocate any buffers, but instead set a few flags and otherwise
      use 0-initialized defaults
    * Implement handle_sock_raw() in src/server.c to check to see if any
      raw frames are pending, and if so, send them to the associated
      interface if provided by setsockopt()
    * Make patty_ax25_sock_bind_if() only call the function
      patty_ax25_if_add_promisc() only if the socket status is PROMISC;
      this allows support for non-promiscuous sockets used for outbound
      purposes
			
			
This commit is contained in:
		
							parent
							
								
									c417461a0b
								
							
						
					
					
						commit
						d0d17b58fb
					
				
					 6 changed files with 88 additions and 44 deletions
				
			
		| 
						 | 
					@ -61,6 +61,8 @@ int main(int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strncpy(ifreq.name, "kiss0", sizeof(ifreq.name));
 | 
					    strncpy(ifreq.name, "kiss0", sizeof(ifreq.name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ifreq.status = PATTY_AX25_SOCK_PROMISC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
 | 
					    if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
 | 
				
			||||||
        fprintf(stderr, "%s: %s: %s\n",
 | 
					        fprintf(stderr, "%s: %s: %s\n",
 | 
				
			||||||
            argv[0], "patty_client_setsockopt()", strerror(errno));
 | 
					            argv[0], "patty_client_setsockopt()", strerror(errno));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,6 +103,8 @@ typedef struct _patty_ax25_sock {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    patty_ax25_if *iface;
 | 
					    patty_ax25_if *iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    patty_kiss_tnc *raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    patty_ax25_addr local,
 | 
					    patty_ax25_addr local,
 | 
				
			||||||
                    remote,
 | 
					                    remote,
 | 
				
			||||||
                    repeaters[PATTY_AX25_MAX_HOPS];
 | 
					                    repeaters[PATTY_AX25_MAX_HOPS];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +58,7 @@ typedef struct _patty_client_setsockopt_request {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _patty_client_setsockopt_if {
 | 
					typedef struct _patty_client_setsockopt_if {
 | 
				
			||||||
    char name[8];
 | 
					    char name[8];
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
} patty_client_setsockopt_if;
 | 
					} patty_client_setsockopt_if;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _patty_client_setsockopt_response {
 | 
					typedef struct _patty_client_setsockopt_response {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								src/if.c
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								src/if.c
									
										
									
									
									
								
							| 
						 | 
					@ -272,21 +272,15 @@ error_ntop:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int patty_ax25_if_promisc_add(patty_ax25_if *iface,
 | 
					int patty_ax25_if_promisc_add(patty_ax25_if *iface,
 | 
				
			||||||
                              int fd) {
 | 
					                              int fd) {
 | 
				
			||||||
    patty_kiss_tnc *tnc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) {
 | 
					    if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) {
 | 
				
			||||||
        errno = EEXIST;
 | 
					        errno = EEXIST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        goto error_exists;
 | 
					        goto error_exists;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((tnc = patty_kiss_tnc_new_fd(fd)) == NULL) {
 | 
					 | 
				
			||||||
        goto error_kiss_tnc_new_fd;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (patty_dict_set(iface->promisc_fds,
 | 
					    if (patty_dict_set(iface->promisc_fds,
 | 
				
			||||||
                       (uint32_t)fd,
 | 
					                       (uint32_t)fd,
 | 
				
			||||||
                       tnc) == NULL) {
 | 
					                       NULL) == NULL) {
 | 
				
			||||||
        errno = ENOMEM;
 | 
					        errno = ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        goto error_dict_set;
 | 
					        goto error_dict_set;
 | 
				
			||||||
| 
						 | 
					@ -295,29 +289,13 @@ int patty_ax25_if_promisc_add(patty_ax25_if *iface,
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_dict_set:
 | 
					error_dict_set:
 | 
				
			||||||
    patty_kiss_tnc_destroy(tnc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
error_kiss_tnc_new_fd:
 | 
					 | 
				
			||||||
error_exists:
 | 
					error_exists:
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int patty_ax25_if_promisc_delete(patty_ax25_if *iface,
 | 
					int patty_ax25_if_promisc_delete(patty_ax25_if *iface,
 | 
				
			||||||
                                 int fd) {
 | 
					                                 int fd) {
 | 
				
			||||||
    patty_kiss_tnc *tnc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((tnc = patty_dict_get(iface->promisc_fds, (uint32_t)fd)) == NULL) {
 | 
					 | 
				
			||||||
        errno = ENOENT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        goto error_notfound;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    patty_kiss_tnc_destroy(tnc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return patty_dict_delete(iface->promisc_fds, (uint32_t)fd);
 | 
					    return patty_dict_delete(iface->promisc_fds, (uint32_t)fd);
 | 
				
			||||||
 | 
					 | 
				
			||||||
error_notfound:
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct promisc_frame {
 | 
					struct promisc_frame {
 | 
				
			||||||
| 
						 | 
					@ -329,10 +307,10 @@ struct promisc_frame {
 | 
				
			||||||
static int handle_promisc_frame(uint32_t key,
 | 
					static int handle_promisc_frame(uint32_t key,
 | 
				
			||||||
                                void *value,
 | 
					                                void *value,
 | 
				
			||||||
                                void *ctx) {
 | 
					                                void *ctx) {
 | 
				
			||||||
    patty_kiss_tnc *tnc = value;
 | 
					    int fd = (int)key;
 | 
				
			||||||
    struct promisc_frame *frame = ctx;
 | 
					    struct promisc_frame *frame = ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return patty_kiss_tnc_send(tnc, frame->buf, frame->len, 0);
 | 
					    return patty_kiss_frame_send(fd, frame->buf, frame->len, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ssize_t patty_ax25_if_pending(patty_ax25_if *iface) {
 | 
					ssize_t patty_ax25_if_pending(patty_ax25_if *iface) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										63
									
								
								src/server.c
									
										
									
									
									
								
							
							
						
						
									
										63
									
								
								src/server.c
									
										
									
									
									
								
							| 
						 | 
					@ -605,6 +605,10 @@ static int server_setsockopt(patty_ax25_server *server,
 | 
				
			||||||
                goto error_read;
 | 
					                goto error_read;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (data.status == PATTY_AX25_SOCK_PROMISC) {
 | 
				
			||||||
 | 
					                sock->status = PATTY_AX25_SOCK_PROMISC;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) {
 | 
					            if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) {
 | 
				
			||||||
                response.ret = -1;
 | 
					                response.ret = -1;
 | 
				
			||||||
                response.eno = ENODEV;
 | 
					                response.eno = ENODEV;
 | 
				
			||||||
| 
						 | 
					@ -614,8 +618,6 @@ static int server_setsockopt(patty_ax25_server *server,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            patty_ax25_sock_bind_if(sock, iface);
 | 
					            patty_ax25_sock_bind_if(sock, iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            sock->status = PATTY_AX25_SOCK_PROMISC;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            fd_watch(server, sock->fd);
 | 
					            fd_watch(server, sock->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -1732,6 +1734,34 @@ error_io:
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int handle_sock_raw(patty_ax25_server *server,
 | 
				
			||||||
 | 
					                           patty_ax25_sock *sock) {
 | 
				
			||||||
 | 
					    ssize_t len;
 | 
				
			||||||
 | 
					    int port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!FD_ISSET(sock->fd, &server->fds_r) || sock->iface == NULL) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((len = patty_kiss_tnc_recv(sock->raw,
 | 
				
			||||||
 | 
					                                   sock->iface->tx_buf,
 | 
				
			||||||
 | 
					                                   sock->iface->mtu,
 | 
				
			||||||
 | 
					                                   &port)) < 0) {
 | 
				
			||||||
 | 
					        goto error_io;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (patty_ax25_if_send(sock->iface,
 | 
				
			||||||
 | 
					                           sock->iface->tx_buf,
 | 
				
			||||||
 | 
					                           len) < 0) {
 | 
				
			||||||
 | 
					        goto error_io;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_io:
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int handle_sock(uint32_t key,
 | 
					static int handle_sock(uint32_t key,
 | 
				
			||||||
                       void *value,
 | 
					                       void *value,
 | 
				
			||||||
                       void *ctx) {
 | 
					                       void *ctx) {
 | 
				
			||||||
| 
						 | 
					@ -1740,6 +1770,10 @@ static int handle_sock(uint32_t key,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ssize_t len;
 | 
					    ssize_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sock->type == PATTY_AX25_SOCK_RAW) {
 | 
				
			||||||
 | 
					        return handle_sock_raw(server, sock);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (sock->status) {
 | 
					    switch (sock->status) {
 | 
				
			||||||
        case PATTY_AX25_SOCK_PENDING_CONNECT:
 | 
					        case PATTY_AX25_SOCK_PENDING_CONNECT:
 | 
				
			||||||
            patty_timer_tick(&sock->timer_t1, &server->elapsed);
 | 
					            patty_timer_tick(&sock->timer_t1, &server->elapsed);
 | 
				
			||||||
| 
						 | 
					@ -1821,15 +1855,14 @@ static int handle_sock(uint32_t key,
 | 
				
			||||||
        goto done;
 | 
					        goto done;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (sock->type == PATTY_AX25_SOCK_STREAM) {
 | 
					    /*
 | 
				
			||||||
        /*
 | 
					     * NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
 | 
				
			||||||
         * NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
 | 
					     */
 | 
				
			||||||
         */
 | 
					    if (sock->vs + sock->n_window_tx == sock->vs) {
 | 
				
			||||||
        if (sock->vs + sock->n_window_tx == sock->vs) {
 | 
					        fd_clear(server, sock->fd);
 | 
				
			||||||
            fd_clear(server, sock->fd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            goto done;
 | 
					        return patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_COMMAND, 1);
 | 
				
			||||||
        }
 | 
					        goto done;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
 | 
					    if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
 | 
				
			||||||
| 
						 | 
					@ -1850,12 +1883,10 @@ static int handle_sock(uint32_t key,
 | 
				
			||||||
        goto error_sock_write;
 | 
					        goto error_sock_write;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (sock->type == PATTY_AX25_SOCK_STREAM) {
 | 
					    /*
 | 
				
			||||||
        /*
 | 
					     * AX.25 v2.2, Section 6.4.1 "Sending I Frames"
 | 
				
			||||||
         * AX.25 v2.2, Section 6.4.1 "Sending I Frames"
 | 
					     */
 | 
				
			||||||
         */
 | 
					    patty_timer_start(&sock->timer_t1, sock->n_ack);
 | 
				
			||||||
        patty_timer_start(&sock->timer_t1, sock->n_ack);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
done:
 | 
					done:
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/sock.c
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								src/sock.c
									
										
									
									
									
								
							| 
						 | 
					@ -111,6 +111,29 @@ error_realloc_tx_buf:
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static patty_ax25_sock *init_raw(patty_ax25_sock *sock) {
 | 
				
			||||||
 | 
					    if (bind_pty(sock) < 0) {
 | 
				
			||||||
 | 
					        goto error_bind_pty;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((sock->raw = patty_kiss_tnc_new_fd(sock->fd)) == NULL) {
 | 
				
			||||||
 | 
					        goto error_kiss_tnc_new_fd;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sock->proto = PATTY_AX25_PROTO_NONE;
 | 
				
			||||||
 | 
					    sock->type  = PATTY_AX25_SOCK_RAW;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return sock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_kiss_tnc_new_fd:
 | 
				
			||||||
 | 
					    (void)close(sock->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_bind_pty:
 | 
				
			||||||
 | 
					    free(sock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
 | 
					patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
 | 
				
			||||||
                                     enum patty_ax25_sock_type type) {
 | 
					                                     enum patty_ax25_sock_type type) {
 | 
				
			||||||
    patty_ax25_sock *sock;
 | 
					    patty_ax25_sock *sock;
 | 
				
			||||||
| 
						 | 
					@ -121,6 +144,10 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(sock, '\0', sizeof(*sock));
 | 
					    memset(sock, '\0', sizeof(*sock));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (type == PATTY_AX25_SOCK_RAW) {
 | 
				
			||||||
 | 
					        return init_raw(sock);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    patty_ax25_sock_init(sock);
 | 
					    patty_ax25_sock_init(sock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sock->proto         = proto;
 | 
					    sock->proto         = proto;
 | 
				
			||||||
| 
						 | 
					@ -160,6 +187,10 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
 | 
				
			||||||
        close(sock->fd);
 | 
					        close(sock->fd);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sock->raw) {
 | 
				
			||||||
 | 
					        patty_kiss_tnc_destroy(sock->raw);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    free(sock->tx_slots);
 | 
					    free(sock->tx_slots);
 | 
				
			||||||
    free(sock->rx_buf);
 | 
					    free(sock->rx_buf);
 | 
				
			||||||
    free(sock->tx_buf);
 | 
					    free(sock->tx_buf);
 | 
				
			||||||
| 
						 | 
					@ -315,15 +346,14 @@ char *patty_ax25_sock_pty(patty_ax25_sock *sock) {
 | 
				
			||||||
int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
 | 
					int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
 | 
				
			||||||
                            patty_ax25_if *iface) {
 | 
					                            patty_ax25_if *iface) {
 | 
				
			||||||
    sock->iface = iface;
 | 
					    sock->iface = iface;
 | 
				
			||||||
 | 
					    sock->flags_classes |= iface->flags_classes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (sock->type == PATTY_AX25_SOCK_RAW) {
 | 
					    if (sock->status == PATTY_AX25_SOCK_PROMISC) {
 | 
				
			||||||
        if (patty_ax25_if_promisc_add(iface, sock->fd) < 0) {
 | 
					        if (patty_ax25_if_promisc_add(iface, sock->fd) < 0) {
 | 
				
			||||||
            goto error_if_promisc_add;
 | 
					            goto error_if_promisc_add;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sock->flags_classes |= iface->flags_classes;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_if_promisc_add:
 | 
					error_if_promisc_add:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue