/** * Open location * * @v intf Data transfer interface * @v type Location type * @v args Remaining arguments depend upon location type * @ret rc Return status code */ int xfer_vopen ( struct interface *intf, int type, va_list args ) { switch ( type ) { case LOCATION_URI_STRING: { const char *uri_string = va_arg ( args, const char * ); return xfer_open_uri_string ( intf, uri_string ); } case LOCATION_URI: { struct uri *uri = va_arg ( args, struct uri * ); return xfer_open_uri ( intf, uri ); } case LOCATION_SOCKET: { int semantics = va_arg ( args, int ); struct sockaddr *peer = va_arg ( args, struct sockaddr * ); struct sockaddr *local = va_arg ( args, struct sockaddr * ); return xfer_open_socket ( intf, semantics, peer, local ); } default: DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to " "open unsupported location type %d\n", INTF_DBG ( intf ), type ); return -ENOTSUP; } }
/** * 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; }
/** * 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; }
/** * Resolve name using DNS * * @v resolv Name resolution interface * @v name Name to resolve * @v sa Socket address to fill in * @ret rc Return status code */ static int dns_resolv ( struct resolv_interface *resolv, const char *name, struct sockaddr *sa ) { struct dns_request *dns; char *fqdn; int rc; /* Fail immediately if no DNS servers */ if ( ! nameserver.st_family ) { DBG ( "DNS not attempting to resolve \"%s\": " "no DNS servers\n", name ); rc = -ENXIO; goto err_no_nameserver; } /* Ensure fully-qualified domain name if DHCP option was given */ fqdn = dns_qualify_name ( name ); if ( ! fqdn ) { rc = -ENOMEM; goto err_qualify_name; } /* Allocate DNS structure */ dns = zalloc ( sizeof ( *dns ) ); if ( ! dns ) { rc = -ENOMEM; goto err_alloc_dns; } resolv_init ( &dns->resolv, &null_resolv_ops, &dns->refcnt ); xfer_init ( &dns->socket, &dns_socket_operations, &dns->refcnt ); dns->timer.expired = dns_timer_expired; memcpy ( &dns->sa, sa, sizeof ( dns->sa ) ); /* Create query */ dns->query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY | DNS_FLAG_RD ); dns->query.dns.qdcount = htons ( 1 ); dns->qinfo = ( void * ) dns_make_name ( fqdn, dns->query.payload ); dns->qinfo->qtype = htons ( DNS_TYPE_A ); dns->qinfo->qclass = htons ( DNS_CLASS_IN ); /* Open UDP connection */ if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM, ( struct sockaddr * ) &nameserver, NULL ) ) != 0 ) { DBGC ( dns, "DNS %p could not open socket: %s\n", dns, strerror ( rc ) ); goto err_open_socket; } /* Send first DNS packet */ dns_send_packet ( dns ); /* Attach parent interface, mortalise self, and return */ resolv_plug_plug ( &dns->resolv, resolv ); ref_put ( &dns->refcnt ); free ( fqdn ); return 0; err_open_socket: err_alloc_dns: ref_put ( &dns->refcnt ); err_qualify_name: free ( fqdn ); err_no_nameserver: return rc; }