/** * Read from block device * * @v http HTTP transaction * @v data Data interface * @v lba Starting logical block address * @v count Number of logical blocks * @v buffer Data buffer * @v len Length of data buffer * @ret rc Return status code */ int http_block_read ( struct http_transaction *http, struct interface *data, uint64_t lba, unsigned int count, userptr_t buffer, size_t len ) { struct http_request_range range; int rc; /* Sanity check */ assert ( len == ( count * HTTP_BLKSIZE ) ); /* Construct request range descriptor */ range.start = ( lba * HTTP_BLKSIZE ); range.len = len; /* Start a range request to retrieve the block(s) */ if ( ( rc = http_open ( data, &http_get, http->uri, &range, NULL ) ) != 0 ) goto err_open; /* Insert block device translator */ if ( ( rc = block_translate ( data, buffer, len ) ) != 0 ) { DBGC ( http, "HTTP %p could not insert block translator: %s\n", http, strerror ( rc ) ); goto err_translate; } return 0; err_translate: intf_restart ( data, rc ); err_open: return rc; }
/** * Child finished resolution * * @v mux Name resolution multiplexer * @v rc Return status code */ static void resmux_child_close ( struct resolv_mux *mux, int rc ) { /* Restart child interface */ intf_restart ( &mux->child, rc ); /* If this resolution succeeded, stop now */ if ( rc == 0 ) { DBGC ( mux, "RESOLV %p succeeded using method %s\n", mux, mux->resolver->name ); goto finished; } /* Attempt next child resolver, if possible */ mux->resolver++; if ( mux->resolver >= table_end ( RESOLVERS ) ) { DBGC ( mux, "RESOLV %p failed to resolve name\n", mux ); goto finished; } if ( ( rc = resmux_try ( mux ) ) != 0 ) goto finished; /* Next resolver is now running */ return; finished: intf_shutdown ( &mux->parent, rc ); }
/** * Reopen location * * @v intf Data transfer interface * @v type Location type * @v args Remaining arguments depend upon location type * @ret rc Return status code * * This will close the existing connection and open a new connection * using xfer_vopen(). It is intended to be used as a .vredirect * method handler. */ int xfer_vreopen ( struct interface *intf, int type, va_list args ) { /* Close existing connection */ intf_restart ( intf, 0 ); /* Open new location */ return xfer_vopen ( intf, type, args ); }
/** * UDP CLOSE * * @v pxenv_udp_close Pointer to a struct s_PXENV_UDP_CLOSE * @ret #PXENV_EXIT_SUCCESS Always * @ret s_PXENV_UDP_CLOSE::Status PXE status code * @err None - * * Closes a UDP connection opened with pxenv_udp_open(). * * You can only have one open UDP connection at a time. You cannot * have a UDP connection open at the same time as a TFTP connection. * You cannot use pxenv_udp_close() to close a TFTP connection; use * pxenv_tftp_close() instead. * * On x86, you must set the s_PXE::StatusCallout field to a nonzero * value before calling this function in protected mode. You cannot * call this function with a 32-bit stack segment. (See the relevant * @ref pxe_x86_pmode16 "implementation note" for more details.) * */ PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) { DBG ( "PXENV_UDP_CLOSE\n" ); /* Close UDP connection */ intf_restart ( &pxe_udp.xfer, 0 ); pxenv_udp_close->Status = PXENV_STATUS_SUCCESS; return PXENV_EXIT_SUCCESS; }
/** * Close an object interface * * @v intf Object interface * @v rc Reason for close * * Note that this function merely informs the destination object that * the interface is about to be closed; it doesn't actually disconnect * the interface. In most cases, you probably want to use * intf_shutdown() or intf_restart() instead. */ void intf_close ( struct interface *intf, int rc ) { struct interface *dest; intf_close_TYPE ( void * ) *op = intf_get_dest_op ( intf, intf_close, &dest ); void *object = intf_object ( dest ); DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n", INTF_INTF_DBG ( intf, dest ), strerror ( rc ) ); if ( op ) { op ( object, rc ); } else { /* Default is to restart the interface */ intf_restart ( dest, rc ); } intf_put ( dest ); }
/** * Apply syslog settings * * @ret rc Return status code */ static int apply_syslog_settings ( void ) { struct sockaddr_in *sin_logserver = ( struct sockaddr_in * ) &logserver; struct in_addr old_addr; int len; int rc; /* Fetch log server */ syslog_console.disabled = 1; old_addr.s_addr = sin_logserver->sin_addr.s_addr; if ( ( len = fetch_ipv4_setting ( NULL, &syslog_setting, &sin_logserver->sin_addr ) ) >= 0 ) { syslog_console.disabled = 0; } /* Do nothing unless log server has changed */ if ( sin_logserver->sin_addr.s_addr == old_addr.s_addr ) return 0; /* Reset syslog connection */ intf_restart ( &syslogger, 0 ); /* Do nothing unless we have a log server */ if ( syslog_console.disabled ) { DBG ( "SYSLOG has no log server\n" ); return 0; } /* Connect to log server */ if ( ( rc = xfer_open_socket ( &syslogger, SOCK_DGRAM, ( ( struct sockaddr * ) &logserver ), NULL ) ) != 0 ) { DBG ( "SYSLOG cannot connect to log server: %s\n", strerror ( rc ) ); return rc; } DBG ( "SYSLOG using log server %s\n", inet_ntoa ( sin_logserver->sin_addr ) ); return 0; }
/** * UDP OPEN * * @v pxenv_udp_open Pointer to a struct s_PXENV_UDP_OPEN * @v s_PXENV_UDP_OPEN::src_ip IP address of this station, or 0.0.0.0 * @ret #PXENV_EXIT_SUCCESS Always * @ret s_PXENV_UDP_OPEN::Status PXE status code * @err #PXENV_STATUS_UDP_OPEN UDP connection already open * @err #PXENV_STATUS_OUT_OF_RESOURCES Could not open connection * * Prepares the PXE stack for communication using pxenv_udp_write() * and pxenv_udp_read(). * * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be * recorded and used as the local station's IP address for all further * communication, including communication by means other than * pxenv_udp_write() and pxenv_udp_read(). (If * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address * will remain unchanged.) * * You can only have one open UDP connection at a time. This is not a * meaningful restriction, since pxenv_udp_write() and * pxenv_udp_read() allow you to specify arbitrary local and remote * ports and an arbitrary remote address for each packet. According * to the PXE specifiation, you cannot have a UDP connection open at * the same time as a TFTP connection; this restriction does not apply * to Etherboot. * * On x86, you must set the s_PXE::StatusCallout field to a nonzero * value before calling this function in protected mode. You cannot * call this function with a 32-bit stack segment. (See the relevant * @ref pxe_x86_pmode16 "implementation note" for more details.) * * @note The PXE specification does not make it clear whether the IP * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only * for this UDP connection, or retained for all future communication. * The latter seems more consistent with typical PXE stack behaviour. * * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip * parameter. * */ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) { int rc; DBG ( "PXENV_UDP_OPEN" ); /* Record source IP address */ pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip; DBG ( " %s\n", inet_ntoa ( pxe_udp.local.sin_addr ) ); /* Open promiscuous UDP connection */ intf_restart ( &pxe_udp.xfer, 0 ); if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) { DBG ( "PXENV_UDP_OPEN could not open promiscuous socket: %s\n", strerror ( rc ) ); pxenv_udp_open->Status = PXENV_STATUS ( rc ); return PXENV_EXIT_FAILURE; } pxenv_udp_open->Status = PXENV_STATUS_SUCCESS; return PXENV_EXIT_SUCCESS; }
/** * Open all PeerDist discovery sockets * * @ret rc Return status code */ static int peerdisc_socket_open ( void ) { struct peerdisc_socket *socket; int rc; /* Open each socket */ for_each_table_entry ( socket, PEERDISC_SOCKETS ) { if ( ( rc = xfer_open_socket ( &socket->xfer, SOCK_DGRAM, &socket->address.sa, NULL ) ) != 0 ) { DBGC ( socket, "PEERDISC %s could not open socket: " "%s\n", socket->name, strerror ( rc ) ); goto err; } } return 0; err: for_each_table_entry_continue_reverse ( socket, PEERDISC_SOCKETS ) intf_restart ( &socket->xfer, rc ); return rc; }
/** * Read block device capacity * * @v control Control interface * @v data Data interface * @ret rc Return status code */ int http_block_read_capacity ( struct http_transaction *http, struct interface *data ) { int rc; /* Start a HEAD request to retrieve the capacity */ if ( ( rc = http_open ( data, &http_head, http->uri, NULL, NULL ) ) != 0 ) goto err_open; /* Insert block device translator */ if ( ( rc = block_translate ( data, UNULL, HTTP_BLKSIZE ) ) != 0 ) { DBGC ( http, "HTTP %p could not insert block translator: %s\n", http, strerror ( rc ) ); goto err_translate; } return 0; err_translate: intf_restart ( data, rc ); err_open: return rc; }