itnifl
asked on
Need bundled ATFTP tool for use with ESXi
VMWare OVF tool is bundled so that if I install it on a ESXi, it finds its libraries in the local folder. I would like a atftp tool that is bundled in the same way so I can install and use it on a ESXi server. If I install atftp in for instance Ubuntu and copy it over to the ESXi, then I get the error:
atftp: error while loading shared libraries: libreadline.so.6: cannot open shared object file: No such file or directory
Tried to copy in the missing file, but that doesn't change anything.
atftp: error while loading shared libraries: libreadline.so.6: cannot open shared object file: No such file or directory
Tried to copy in the missing file, but that doesn't change anything.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I used the guide in the link that I pasted in my last reply and compiled this tftp client in Centos 6.7:
It works fine on ESXi when it is compiled as statitically linked:
Just make sure the firewall on the ESXi is disabled:
I wouldn't think it would be a problem, but it was. Maybe because I enabled it this way some time?
The code that lanrat at github has for his tftp client uses a constant for the host address to connect to. This means you will have to change the constant and recompile the code to use it with another server. This is too cumbersome for any later on IT staff member to handle, so I rewrote the tftpclient.c source file. It is not perfect, but now I can pass in a argument to the compiled program that overrides the defined constant if I feel like it.
Now I can use this client in a kickstart script at a ESXi installation to automatically fetch the setup of the ESXi host from a tftp server.
https://github.com/lanrat/tftp
It works fine on ESXi when it is compiled as statitically linked:
make CFLAGS="-static" EXEEXT="-static"
Just make sure the firewall on the ESXi is disabled:
esxcli network firewall set --enabled no
I wouldn't think it would be a problem, but it was. Maybe because I enabled it this way some time?
esxcli network firewall set --default-action false --enabled yes
The code that lanrat at github has for his tftp client uses a constant for the host address to connect to. This means you will have to change the constant and recompile the code to use it with another server. This is too cumbersome for any later on IT staff member to handle, so I rewrote the tftpclient.c source file. It is not perfect, but now I can pass in a argument to the compiled program that overrides the defined constant if I feel like it.
#include "tftp.h"
//returns a struct for the server information
//Original code from https://github.com/lanrat/tftp - thank you lanrat!
//Function is rewritten to avoid use of hard coded hostnames or addresses
struct sockaddr_in getServerStruct(char *host, int port)
{
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(host);
serv_addr.sin_port = htons(port);
return serv_addr;
}
//called when we retrieve a file from the server
//Original code from https://github.com/lanrat/tftp - thank you lanrat!
//Function is slightly rewritten to avoid use of hard coded hostnames or addresses
void getFile(char *host, int port, char *filename)
{
int sockfd;
struct sockaddr_in serv_addr;
FILE * file;
if (strchr(filename,'/') != NULL )
{
printf("We do not support file transfer out of the current working directory\n");
return;
}
file = fopen(filename, "wb");
if(file == NULL)
{
perror(filename);
return;
}
sockfd = createUDPSocketAndBind(0);
serv_addr = getServerStruct(host, port);
if(sockfd < 0)
{
printf("Couldn't open socket\n");
return;
}
if(!send_RRQ(sockfd, (struct sockaddr *) &serv_addr, filename, TFTP_SUPORTED_MODE))
{
printf("Error: couldn't send RRQ\n");
return;
}
if(!recvFile(sockfd, (struct sockaddr *) &serv_addr, file,filename))
{
printf("Error: didn't receive file\n");
return;
}
fclose(file);
return;
}
//used to upload files to the server
//Original code from https://github.com/lanrat/tftp - thank you lanrat!
//Function is slightly rewritten to avoid use of hard coded hostnames or addresses.
void putFile(char *host, int port, char *filename)
{
int sockfd;
struct sockaddr_in serv_addr;
PACKET packet;
int result;
FILE * fileh;
int timeout_counter = 0;
if (strchr(filename,'/') != NULL )
{
printf("We do not support file transfer out of the current working directory\n");
return;
}
fileh = fopen(filename, "rb");
if(fileh == NULL)
{
perror(filename);
return;
}
sockfd = createUDPSocketAndBind(0);
serv_addr = getServerStruct(host, port);
if(sockfd < 0)
{
printf("Couldn't open socket\n");
return;
}
if(!send_WRQ(sockfd, (struct sockaddr *) &serv_addr, filename, TFTP_SUPORTED_MODE))
{
printf("Error: couldn't send WRQ to server\n");
return;
}
while (timeout_counter < MAX_TFTP_TIMEOUTS)
{
result = waitForPacket(sockfd, (struct sockaddr *) &serv_addr, TFTP_OPTCODE_ACK, &packet);
if (result < 0)
{
printf("Error: Timeout sending packet to server\n");
if(!send_WRQ(sockfd, (struct sockaddr *) &serv_addr, filename, TFTP_SUPORTED_MODE))
{
printf("Error: couldn't send WRQ to server\n");
return;
}
timeout_counter++;
}else
{
break;
}
}
if (result < 0)
{
//we still timed out
printf("Timed out after %d tries, is the server running\n",MAX_TFTP_TIMEOUTS);
fclose(fileh);
return;
}
if (packet.optcode == TFTP_OPTCODE_ERR)
{
//we recieved an error, print it
printError(&packet);
}else
{
if (!sendFile(sockfd, (struct sockaddr *) &serv_addr, fileh))
{
printf("Unable to send file to server\n");
}
}
fclose(fileh);
return;
}
//main client, checks for args and starts an operation if no errors detected
//Original code from https://github.com/lanrat/tftp - thank you lanrat!
//Function is rewritten to avoid use of hard coded hostnames or addresses.
int main(int argc, char *argv[])
{
int port = SERV_UDP_PORT;
char *host = SERV_HOST_ADDR;
bool writeFile = false;
bool readFile = false;
int argOffset = 1;
char* filename;
int x = 1;
while (x < argc) {
if (argv[x][0] == '-') {
//printf("Entered at Checking: %c\n", argv[x][1]);
//printf("Variable is: %s\n", argv[x + 1]);
switch (argv[x][1]) {
case 'p':
port = atoi(argv[x + 1]);
break;
case 'h':
host = argv[x + 1];
break;
case 'w':
writeFile = true;
filename = argv[x + 1];
break;
case 'r':
readFile = true;
filename = argv[x + 1];
break;
default:
break;
}
}
x++;
}
//printf("After loop\n");
//printf("Host: %s\n", host);
//printf("Port: %i\n", port);
//printf("Filename: %s\n", filename);
if (writeFile == true) {
putFile(host, port, filename);
}
if (readFile == true) {
getFile(host, port, filename);
}
if (writeFile == false && readFile == false) {
printf("Usage: %s [-h host] [-p port] (-w putfile || -r getFile)\n", argv[0]);
}
}
Now I can use this client in a kickstart script at a ESXi installation to automatically fetch the setup of the ESXi host from a tftp server.
ASKER
Your (Andrew Hancock) reply was a inspiration to the solution. I don't remember how I found the first link, but it somehow led to it via the links you posted.
ASKER
http://www.virtuallyghetto.com/2011/02/how-to-compile-statically-linked-rsync.html
Centos 3 is oudated, and yum does not work any more when using that tool inside Centos 3. So I will take my chances with Centos 6.7 - 32 bit. The guy in the article also used 32 bit when he used Centos 3.