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)); | ||||
| 
 | ||||
|     ifreq.status = PATTY_AX25_SOCK_PROMISC; | ||||
| 
 | ||||
|     if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) { | ||||
|         fprintf(stderr, "%s: %s: %s\n", | ||||
|             argv[0], "patty_client_setsockopt()", strerror(errno)); | ||||
|  |  | |||
|  | @ -103,6 +103,8 @@ typedef struct _patty_ax25_sock { | |||
| 
 | ||||
|     patty_ax25_if *iface; | ||||
| 
 | ||||
|     patty_kiss_tnc *raw; | ||||
| 
 | ||||
|     patty_ax25_addr local, | ||||
|                     remote, | ||||
|                     repeaters[PATTY_AX25_MAX_HOPS]; | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ typedef struct _patty_client_setsockopt_request { | |||
| 
 | ||||
| typedef struct _patty_client_setsockopt_if { | ||||
|     char name[8]; | ||||
|     int status; | ||||
| } patty_client_setsockopt_if; | ||||
| 
 | ||||
| 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 fd) { | ||||
|     patty_kiss_tnc *tnc; | ||||
| 
 | ||||
|     if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) { | ||||
|         errno = EEXIST; | ||||
| 
 | ||||
|         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, | ||||
|                        (uint32_t)fd, | ||||
|                        tnc) == NULL) { | ||||
|                        NULL) == NULL) { | ||||
|         errno = ENOMEM; | ||||
| 
 | ||||
|         goto error_dict_set; | ||||
|  | @ -295,29 +289,13 @@ int patty_ax25_if_promisc_add(patty_ax25_if *iface, | |||
|     return 0; | ||||
| 
 | ||||
| error_dict_set: | ||||
|     patty_kiss_tnc_destroy(tnc); | ||||
| 
 | ||||
| error_kiss_tnc_new_fd: | ||||
| error_exists: | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| int patty_ax25_if_promisc_delete(patty_ax25_if *iface, | ||||
|                                  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); | ||||
| 
 | ||||
| error_notfound: | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| struct promisc_frame { | ||||
|  | @ -329,10 +307,10 @@ struct promisc_frame { | |||
| static int handle_promisc_frame(uint32_t key, | ||||
|                                 void *value, | ||||
|                                 void *ctx) { | ||||
|     patty_kiss_tnc *tnc = value; | ||||
|     int fd = (int)key; | ||||
|     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) { | ||||
|  |  | |||
							
								
								
									
										43
									
								
								src/server.c
									
										
									
									
									
								
							
							
						
						
									
										43
									
								
								src/server.c
									
										
									
									
									
								
							|  | @ -605,6 +605,10 @@ static int server_setsockopt(patty_ax25_server *server, | |||
|                 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) { | ||||
|                 response.ret = -1; | ||||
|                 response.eno = ENODEV; | ||||
|  | @ -614,8 +618,6 @@ static int server_setsockopt(patty_ax25_server *server, | |||
| 
 | ||||
|             patty_ax25_sock_bind_if(sock, iface); | ||||
| 
 | ||||
|             sock->status = PATTY_AX25_SOCK_PROMISC; | ||||
| 
 | ||||
|             fd_watch(server, sock->fd); | ||||
| 
 | ||||
|             break; | ||||
|  | @ -1732,6 +1734,34 @@ error_io: | |||
|     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, | ||||
|                        void *value, | ||||
|                        void *ctx) { | ||||
|  | @ -1740,6 +1770,10 @@ static int handle_sock(uint32_t key, | |||
| 
 | ||||
|     ssize_t len; | ||||
| 
 | ||||
|     if (sock->type == PATTY_AX25_SOCK_RAW) { | ||||
|         return handle_sock_raw(server, sock); | ||||
|     } | ||||
| 
 | ||||
|     switch (sock->status) { | ||||
|         case PATTY_AX25_SOCK_PENDING_CONNECT: | ||||
|             patty_timer_tick(&sock->timer_t1, &server->elapsed); | ||||
|  | @ -1821,16 +1855,15 @@ static int handle_sock(uint32_t key, | |||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     if (sock->type == PATTY_AX25_SOCK_STREAM) { | ||||
|     /*
 | ||||
|      * NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames" | ||||
|      */ | ||||
|     if (sock->vs + sock->n_window_tx == sock->vs) { | ||||
|         fd_clear(server, sock->fd); | ||||
| 
 | ||||
|         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 (errno == EIO) { | ||||
|  | @ -1850,12 +1883,10 @@ static int handle_sock(uint32_t key, | |||
|         goto error_sock_write; | ||||
|     } | ||||
| 
 | ||||
|     if (sock->type == PATTY_AX25_SOCK_STREAM) { | ||||
|     /*
 | ||||
|      * AX.25 v2.2, Section 6.4.1 "Sending I Frames" | ||||
|      */ | ||||
|     patty_timer_start(&sock->timer_t1, sock->n_ack); | ||||
|     } | ||||
| 
 | ||||
| done: | ||||
|     return 0; | ||||
|  |  | |||
							
								
								
									
										36
									
								
								src/sock.c
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								src/sock.c
									
										
									
									
									
								
							|  | @ -111,6 +111,29 @@ error_realloc_tx_buf: | |||
|     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, | ||||
|                                      enum patty_ax25_sock_type type) { | ||||
|     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)); | ||||
| 
 | ||||
|     if (type == PATTY_AX25_SOCK_RAW) { | ||||
|         return init_raw(sock); | ||||
|     } | ||||
| 
 | ||||
|     patty_ax25_sock_init(sock); | ||||
| 
 | ||||
|     sock->proto         = proto; | ||||
|  | @ -160,6 +187,10 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) { | |||
|         close(sock->fd); | ||||
|     } | ||||
| 
 | ||||
|     if (sock->raw) { | ||||
|         patty_kiss_tnc_destroy(sock->raw); | ||||
|     } | ||||
| 
 | ||||
|     free(sock->tx_slots); | ||||
|     free(sock->rx_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, | ||||
|                             patty_ax25_if *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) { | ||||
|             goto error_if_promisc_add; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     sock->flags_classes |= iface->flags_classes; | ||||
| 
 | ||||
|     return 0; | ||||
| 
 | ||||
| error_if_promisc_add: | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue