333 lines
6.7 KiB
C
333 lines
6.7 KiB
C
/*
|
|
* ncpmount.c
|
|
*
|
|
* Copyright (C) 1995 by Volker Lendecke
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <pwd.h>
|
|
#include <grp.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/param.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
/* #include <sys/wait.h> */ /* generates a warning here */
|
|
extern pid_t waitpid(pid_t, int *, int);
|
|
#include <sys/errno.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mount.h>
|
|
#include <mntent.h>
|
|
#include <linux/ipx.h>
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/ncp.h>
|
|
#include <linux/ncp_fs.h>
|
|
#include <linux/ncp_mount.h>
|
|
#include "ipxutil.h"
|
|
|
|
static char *progname;
|
|
static char *mount_point;
|
|
static char *server_name;
|
|
|
|
struct sap_query {
|
|
unsigned short query_type; /* net order */
|
|
unsigned short server_type; /* net order */
|
|
};
|
|
|
|
struct sap_server_ident {
|
|
unsigned short server_type;
|
|
char server_name[48];
|
|
IPXNet server_network;
|
|
IPXNode server_node;
|
|
IPXPort server_port;
|
|
unsigned short intermediate_network;
|
|
} __attribute__ ((packed));
|
|
|
|
|
|
void
|
|
ipx_fprint_node(FILE* file,IPXNode node)
|
|
{
|
|
fprintf(file,"%02X%02X%02X%02X%02X%02X",
|
|
(unsigned char)node[0],
|
|
(unsigned char)node[1],
|
|
(unsigned char)node[2],
|
|
(unsigned char)node[3],
|
|
(unsigned char)node[4],
|
|
(unsigned char)node[5]
|
|
);
|
|
}
|
|
|
|
void
|
|
ipx_fprint_network(FILE* file,IPXNet net)
|
|
{
|
|
fprintf(file,"%08lX",ntohl(net));
|
|
}
|
|
|
|
void
|
|
ipx_fprint_port(FILE* file,IPXPort port)
|
|
{
|
|
fprintf(file,"%04X",ntohs(port));
|
|
}
|
|
|
|
void
|
|
ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx)
|
|
{
|
|
ipx_fprint_network(file,sipx->sipx_network);
|
|
fprintf(file,":");
|
|
ipx_fprint_node(file,sipx->sipx_node);
|
|
fprintf(file,":");
|
|
ipx_fprint_port(file,sipx->sipx_port);
|
|
}
|
|
|
|
void
|
|
ipx_print_node(IPXNode node)
|
|
{
|
|
ipx_fprint_node(stdout,node);
|
|
}
|
|
|
|
void
|
|
ipx_print_network(IPXNet net)
|
|
{
|
|
ipx_fprint_network(stdout,net);
|
|
}
|
|
|
|
void
|
|
ipx_print_port(IPXPort port)
|
|
{
|
|
ipx_fprint_port(stdout,port);
|
|
}
|
|
|
|
void
|
|
ipx_print_saddr(struct sockaddr_ipx* sipx)
|
|
{
|
|
ipx_fprint_saddr(stdout,sipx);
|
|
}
|
|
|
|
int
|
|
ipx_sap_find_server(char *name, int server_type, int timeout,
|
|
struct sockaddr_ipx *result)
|
|
{
|
|
struct sockaddr_ipx ipxs;
|
|
char data[1024];
|
|
int sock;
|
|
int opt;
|
|
int res = -1;
|
|
int name_len = strlen(name);
|
|
fd_set rd, wr, ex;
|
|
struct timeval tv;
|
|
|
|
if (name_len > 48) {
|
|
return -1;
|
|
}
|
|
|
|
sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
|
|
if (sock==-1) {
|
|
return -1;
|
|
}
|
|
|
|
opt=1;
|
|
/* Permit broadcast output */
|
|
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1)
|
|
{
|
|
perror("setsockopt");
|
|
goto finished;
|
|
}
|
|
|
|
memset(&ipxs, 0, sizeof(ipxs));
|
|
ipxs.sipx_family=AF_IPX;
|
|
ipxs.sipx_network=htonl(0x0);
|
|
ipxs.sipx_port=htons(0x0);
|
|
ipxs.sipx_type=IPX_SAP_PTYPE;
|
|
|
|
if(bind(sock,(struct sockaddr*)&ipxs,sizeof(ipxs))==-1)
|
|
{
|
|
perror("bind");
|
|
goto finished;
|
|
}
|
|
|
|
*(unsigned short *)data = htons(0x0001);
|
|
*(unsigned short *)&(data[2]) = htons(server_type);
|
|
|
|
memset(&ipxs, 0, sizeof(ipxs));
|
|
ipxs.sipx_family=AF_IPX;
|
|
ipxs.sipx_network=htonl(0x0);
|
|
ipx_assign_node(ipxs.sipx_node, IPX_BROADCAST_NODE);
|
|
ipxs.sipx_port=htons(IPX_SAP_PORT);
|
|
ipxs.sipx_type=IPX_SAP_PTYPE;
|
|
|
|
if (sendto(sock, data, 4, 0,
|
|
(struct sockaddr *)&ipxs, sizeof(ipxs)) < 0) {
|
|
perror("sendto");
|
|
goto finished;
|
|
}
|
|
|
|
FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex);
|
|
FD_SET(sock, &rd);
|
|
|
|
tv.tv_sec = timeout;
|
|
tv.tv_usec = 0;
|
|
|
|
if (select(sock+1, &rd, &wr, &ex, &tv) == -1) {
|
|
perror("select");
|
|
goto finished;
|
|
}
|
|
|
|
if (FD_ISSET(sock, &rd)) {
|
|
int len = recv(sock, data, 1024, 0);
|
|
int i;
|
|
struct sap_server_ident *ident;
|
|
|
|
for (i = 2; i < len; i += 64) {
|
|
ident = (struct sap_server_ident *)(data+i);
|
|
if ( (strncmp(name,ident->server_name,name_len)==0)
|
|
&& (name_len < 48)
|
|
&& (ident->server_name[name_len] == '\0'))
|
|
{
|
|
result->sipx_family = AF_IPX;
|
|
result->sipx_network =
|
|
ident->server_network;
|
|
result->sipx_port = ident->server_port;
|
|
ipx_assign_node(result->sipx_node,
|
|
ident->server_node);
|
|
res = 0;
|
|
goto finished;
|
|
}
|
|
}
|
|
}
|
|
|
|
finished:
|
|
close(sock);
|
|
return res;
|
|
}
|
|
|
|
int ipx_sscanf_node(char *buf, unsigned char node[6])
|
|
{
|
|
int i;
|
|
int n[6];
|
|
|
|
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
|
&(n[0]), &(n[1]), &(n[2]),
|
|
&(n[3]), &(n[4]), &(n[5]))) != 6) {
|
|
return i;
|
|
}
|
|
|
|
for (i=0; i<6; i++) {
|
|
node[i] = n[i];
|
|
}
|
|
return 6;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
struct ncp_mount_data data;
|
|
struct stat st;
|
|
struct sockaddr_ipx addr;
|
|
int ncp_sock, wdog_sock;
|
|
int flags;
|
|
|
|
progname = argv[0];
|
|
|
|
if (geteuid() != 0) {
|
|
fprintf(stderr, "%s must be installed suid root\n", progname);
|
|
exit(1);
|
|
}
|
|
|
|
memset(&data, 0, sizeof(struct ncp_mount_data));
|
|
|
|
if (argc != 5) {
|
|
fprintf(stderr, "usage: %s server mount-point"
|
|
" user password\n", progname);
|
|
exit(1);
|
|
}
|
|
|
|
server_name = argv[1];
|
|
mount_point = argv[2];
|
|
|
|
|
|
if (stat(mount_point, &st) == -1) {
|
|
fprintf(stderr, "could not find mount point %s: %s\n",
|
|
mount_point, strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
|
if (ncp_sock == -1) {
|
|
fprintf(stderr, "could not open ncp socket: %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
wdog_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
|
if (wdog_sock == -1) {
|
|
fprintf(stderr, "could not open wdog socket: %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
addr.sipx_type = NCP_PTYPE;
|
|
|
|
if (bind(ncp_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
|
fprintf(stderr, "bind(ncp_sock, ): %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
if (bind(wdog_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
|
fprintf(stderr, "bind(wdog_sock, ): %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
if (ipx_sap_find_server(server_name, IPX_SAP_FILE_SERVER,
|
|
3, &addr) != 0) {
|
|
fprintf(stderr, "could not find server %s\n", server_name);
|
|
exit(1);
|
|
}
|
|
|
|
printf("server: ");
|
|
ipx_fprint_saddr(stdout, &addr);
|
|
printf("\n");
|
|
|
|
data.version = NCP_MOUNT_VERSION;
|
|
data.ncp_fd = ncp_sock;
|
|
data.wdog_fd = wdog_sock;
|
|
data.mounted_uid = getuid();
|
|
data.serv_addr = addr;
|
|
strcpy(data.server_name, server_name);
|
|
data.time_out = 20; /* 2 seconds */
|
|
data.retry_count = 2;
|
|
data.uid = 501; /* me */
|
|
data.gid = 100; /* users */
|
|
data.file_mode = data.dir_mode = S_IRWXU|S_IRWXG|S_IRWXO;
|
|
strcpy(data.username, argv[3]);
|
|
strcpy(data.password, argv[4]);
|
|
|
|
flags = MS_MGC_VAL;
|
|
|
|
if (mount(NULL, mount_point, "ncpfs", flags, (char *)&data) < 0) {
|
|
perror("mount error");
|
|
fprintf(stderr, "Maybe you should try your password in "
|
|
"upper case\n");
|
|
return -1;
|
|
}
|
|
|
|
close(ncp_sock);
|
|
close(wdog_sock);
|
|
|
|
return 0;
|
|
}
|
|
|