Commit f91748e6 authored by Rusty Russell's avatar Rusty Russell

nfs: initial import.

Another Ronnie module!
parent b581c238
CC=gcc
CFLAGS=-g -O0 -Wall -W -I. "-D_U_=__attribute__((unused))" -D_FILE_OFFSET_BITS=64
LIBS=
LIBNFS_OBJ = libnfs-raw-mount.o libnfs-raw-portmap.o libnfs-raw-nfs.o libnfs-raw-nfsacl.o mount.o nfs.o nfsacl.o portmap.o pdu.o init.o socket.o libnfs.o libnfs-sync.o
all: nfsclient-raw nfsclient-async nfsclient-sync
nfsclient-async: nfsclient-async.c libnfs.a
$(CC) -o $@ nfsclient-async.c libnfs.a $(LIBS)
nfsclient-sync: nfsclient-sync.c libnfs.a
$(CC) -o $@ nfsclient-sync.c libnfs.a $(LIBS)
nfsclient-raw: nfsclient-raw.c libnfs.a
$(CC) -o $@ nfsclient-raw.c libnfs.a $(LIBS)
libnfs.a: $(LIBNFS_OBJ)
@echo Creating library $@
ar r libnfs.a $(LIBNFS_OBJ)
ranlib libnfs.a
libnfs-raw-mount.h: mount.x
@echo Generating $@
rpcgen -h mount.x > libnfs-raw-mount.h
libnfs-raw-mount.c: mount.x
@echo Generating $@
rpcgen -c mount.x | sed -e "s/#include \"mount.h\"/#include \"libnfs-raw-mount.h\"/" > libnfs-raw-mount.c
libnfs-raw-mount.o: libnfs-raw-mount.c libnfs-raw-mount.h
@echo Compiling $@
gcc -g -c libnfs-raw-mount.c -o $@
libnfs-raw-nfs.h: nfs.x
@echo Generating $@
rpcgen -h nfs.x > libnfs-raw-nfs.h
libnfs-raw-nfs.c: nfs.x
@echo Generating $@
rpcgen -c nfs.x | sed -e "s/#include \"nfs.h\"/#include \"libnfs-raw-nfs.h\"/" > libnfs-raw-nfs.c
libnfs-raw-nfs.o: libnfs-raw-nfs.c libnfs-raw-nfs.h
@echo Compiling $@
gcc -g -c libnfs-raw-nfs.c -o $@
libnfs-raw-nfsacl.h: nfsacl.x
@echo Generating $@
rpcgen -h nfsacl.x > libnfs-raw-nfsacl.h
libnfs-raw-nfsacl.c: nfsacl.x
@echo Generating $@
rpcgen -c nfsacl.x | sed -e "s/#include \"nfsacl.h\"/#include \"libnfs-raw-nfsacl.h\"/" > libnfs-raw-nfsacl.c
libnfs-raw-nfsacl.o: libnfs-raw-nfsacl.c libnfs-raw-nfsacl.h
@echo Compiling $@
gcc -g -c libnfs-raw-nfsacl.c -o $@
libnfs-raw-portmap.h: portmap.x
@echo Generating $@
rpcgen -h portmap.x > libnfs-raw-portmap.h
libnfs-raw-portmap.c: portmap.x
@echo Generating $@
rpcgen -c portmap.x | sed -e "s/#include \"portmap.h\"/#include \"libnfs-raw-portmap.h\"/" > libnfs-raw-portmap.c
libnfs-raw-portmap.o: libnfs-raw-portmap.c libnfs-raw-portmap.h
@echo Compiling $@
gcc -g -c libnfs-raw-portmap.c -o $@
clean:
rm -f *.o
rm -f *.a
rm -f libnfs-raw-mount.h libnfs-raw-mount.c
rm -f libnfs-raw-nfs.h libnfs-raw-nfs.c
rm -f libnfs-raw-nfsacl.h libnfs-raw-nfsacl.c
rm -f libnfs-raw-portmap.h libnfs-raw-portmap.c
rm -f nfsclient-raw nfsclient-async nfsclient-sync
/*
Unix SMB/CIFS implementation.
some simple double linked list macros
Copyright (C) Andrew Tridgell 1998-2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* To use these macros you must have a structure containing a next and
prev pointer */
#ifndef _DLINKLIST_H
#define _DLINKLIST_H
/*
February 2010 - changed list format to have a prev pointer from the
list head. This makes DLIST_ADD_END() O(1) even though we only have
one list pointer.
The scheme is as follows:
1) with no entries in the list:
list_head == NULL
2) with 1 entry in the list:
list_head->next == NULL
list_head->prev == list_head
3) with 2 entries in the list:
list_head->next == element2
list_head->prev == element2
element2->prev == list_head
element2->next == NULL
4) with N entries in the list:
list_head->next == element2
list_head->prev == elementN
elementN->prev == element{N-1}
elementN->next == NULL
This allows us to find the tail of the list by using
list_head->prev, which means we can add to the end of the list in
O(1) time
Note that the 'type' arguments below are no longer needed, but
are kept for now to prevent an incompatible argument change
*/
/*
add an element at the front of a list
*/
#define DLIST_ADD(list, p) \
do { \
if (!(list)) { \
(p)->prev = (list) = (p); \
(p)->next = NULL; \
} else { \
(p)->prev = (list)->prev; \
(list)->prev = (p); \
(p)->next = (list); \
(list) = (p); \
} \
} while (0)
/*
remove an element from a list
Note that the element doesn't have to be in the list. If it
isn't then this is a no-op
*/
#define DLIST_REMOVE(list, p) \
do { \
if ((p) == (list)) { \
if ((p)->next) (p)->next->prev = (p)->prev; \
(list) = (p)->next; \
} else if ((list) && (p) == (list)->prev) { \
(p)->prev->next = NULL; \
(list)->prev = (p)->prev; \
} else { \
if ((p)->prev) (p)->prev->next = (p)->next; \
if ((p)->next) (p)->next->prev = (p)->prev; \
} \
if ((p) != (list)) (p)->next = (p)->prev = NULL; \
} while (0)
/*
find the head of the list given any element in it.
Note that this costs O(N), so you should avoid this macro
if at all possible!
*/
#define DLIST_HEAD(p, result_head) \
do { \
(result_head) = (p); \
while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
} while(0)
/* return the last element in the list */
#define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
/* return the previous element in the list. */
#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
/* insert 'p' after the given element 'el' in a list. If el is NULL then
this is the same as a DLIST_ADD() */
#define DLIST_ADD_AFTER(list, p, el) \
do { \
if (!(list) || !(el)) { \
DLIST_ADD(list, p); \
} else { \
(p)->prev = (el); \
(p)->next = (el)->next; \
(el)->next = (p); \
if ((p)->next) (p)->next->prev = (p); \
if ((list)->prev == (el)) (list)->prev = (p); \
}\
} while (0)
/*
add to the end of a list.
Note that 'type' is ignored
*/
#define DLIST_ADD_END(list, p, type) \
do { \
if (!(list)) { \
DLIST_ADD(list, p); \
} else { \
DLIST_ADD_AFTER(list, p, (list)->prev); \
} \
} while (0)
/* promote an element to the from of a list */
#define DLIST_PROMOTE(list, p) \
do { \
DLIST_REMOVE(list, p); \
DLIST_ADD(list, p); \
} while (0)
/*
demote an element to the end of a list.
Note that 'type' is ignored
*/
#define DLIST_DEMOTE(list, p, type) \
do { \
DLIST_REMOVE(list, p); \
DLIST_ADD_END(list, p, NULL); \
} while (0)
/*
concatenate two lists - putting all elements of the 2nd list at the
end of the first list.
Note that 'type' is ignored
*/
#define DLIST_CONCATENATE(list1, list2, type) \
do { \
if (!(list1)) { \
(list1) = (list2); \
} else { \
(list1)->prev->next = (list2); \
if (list2) { \
void *_tmplist = (void *)(list1)->prev; \
(list1)->prev = (list2)->prev; \
(list2)->prev = _tmplist; \
} \
} \
} while (0)
#endif /* _DLINKLIST_H */
/*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <rpc/xdr.h>
#include "dlinklist.h"
#include "libnfs.h"
#include "libnfs-raw.h"
#include "libnfs-private.h"
struct rpc_context *rpc_init_context(void)
{
struct rpc_context *rpc;
rpc = malloc(sizeof(struct rpc_context));
if (rpc == NULL) {
printf("Failed to allocate rpc context\n");
return NULL;
}
bzero(rpc, sizeof(struct rpc_context));
rpc->encodebuflen = 65536;
rpc->encodebuf = malloc(rpc->encodebuflen);
if (rpc->encodebuf == NULL) {
printf("Failed to allocate a buffer for rpc encoding\n");
free(rpc);
return NULL;
}
rpc->auth = authunix_create_default();
if (rpc->auth == NULL) {
printf("failed to create authunix\n");
free(rpc->encodebuf);
free(rpc);
return NULL;
}
rpc->xid = 1;
rpc->fd = -1;
return rpc;
}
void rpc_set_auth(struct rpc_context *rpc, struct AUTH *auth)
{
if (rpc->auth != NULL) {
auth_destroy(rpc->auth);
}
rpc->auth = auth;
}
void rpc_set_error(struct rpc_context *rpc, char *error_string, ...)
{
va_list ap;
char *str;
if (rpc->error_string != NULL) {
free(rpc->error_string);
}
va_start(ap, error_string);
vasprintf(&str, error_string, ap);
rpc->error_string = str;
va_end(ap);
}
char *rpc_get_error(struct rpc_context *rpc)
{
return rpc->error_string;
}
void rpc_error_all_pdus(struct rpc_context *rpc, char *error)
{
struct rpc_pdu *pdu;
while((pdu = rpc->outqueue) != NULL) {
pdu->cb(rpc, RPC_STATUS_ERROR, error, pdu->private_data);
DLIST_REMOVE(rpc->outqueue, pdu);
rpc_free_pdu(rpc, pdu);
}
while((pdu = rpc->waitpdu) != NULL) {
pdu->cb(rpc, RPC_STATUS_ERROR, error, pdu->private_data);
DLIST_REMOVE(rpc->waitpdu, pdu);
rpc_free_pdu(rpc, pdu);
}
}
void rpc_destroy_context(struct rpc_context *rpc)
{
struct rpc_pdu *pdu;
while((pdu = rpc->outqueue) != NULL) {
pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data);
DLIST_REMOVE(rpc->outqueue, pdu);
rpc_free_pdu(rpc, pdu);
}
while((pdu = rpc->waitpdu) != NULL) {
pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data);
DLIST_REMOVE(rpc->waitpdu, pdu);
rpc_free_pdu(rpc, pdu);
}
auth_destroy(rpc->auth);
rpc->auth =NULL;
if (rpc->fd != -1) {
close(rpc->fd);
}
if (rpc->encodebuf != NULL) {
free(rpc->encodebuf);
rpc->encodebuf = NULL;
}
if (rpc->error_string != NULL) {
free(rpc->error_string);
rpc->error_string = NULL;
}
free(rpc);
}
/*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <rpc/auth.h>
struct rpc_context {
int fd;
int is_connected;
char *error_string;
rpc_cb connect_cb;
void *connect_data;
AUTH *auth;
unsigned long xid;
/* buffer used for encoding RPC PDU */
char *encodebuf;
int encodebuflen;
struct rpc_pdu *outqueue;
struct rpc_pdu *waitpdu;
int insize;
int inpos;
char *inbuf;
};
struct rpc_pdu {
struct rpc_pdu *prev, *next;
unsigned long xid;
XDR xdr;
int written;
struct rpc_data outdata;
rpc_cb cb;
void *private_data;
/* function to decode the xdr reply data and buffer to decode into */
xdrproc_t xdr_decode_fn;
caddr_t xdr_decode_buf;
int xdr_decode_bufsize;
};
struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, xdrproc_t xdr_decode_fn, int xdr_bufsize);
void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu);
int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu);
int rpc_get_pdu_size(char *buf);
int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size);
void rpc_error_all_pdus(struct rpc_context *rpc, char *error);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* copied from RFC1813 */
const MNTPATHLEN = 1024; /* Maximum bytes in a path name */
const MNTNAMLEN = 255; /* Maximum bytes in a name */
const FHSIZE3 = 64; /* Maximum bytes in a V3 file handle */
typedef opaque fhandle3<FHSIZE3>;
typedef string dirpath<MNTPATHLEN>;
typedef string name<MNTNAMLEN>;
enum mountstat3 {
MNT3_OK = 0, /* no error */
MNT3ERR_PERM = 1, /* Not owner */
MNT3ERR_NOENT = 2, /* No such file or directory */
MNT3ERR_IO = 5, /* I/O error */
MNT3ERR_ACCES = 13, /* Permission denied */
MNT3ERR_NOTDIR = 20, /* Not a directory */
MNT3ERR_INVAL = 22, /* Invalid argument */
MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */
};
typedef struct mountbody *mountlist;
struct mountbody {
name ml_hostname;
dirpath ml_directory;
mountlist ml_next;
};
typedef struct groupnode *groups;
struct groupnode {
name gr_name;
groups gr_next;
};
typedef struct exportnode *exports;
struct exportnode {
dirpath ex_dir;
groups ex_groups;
exports ex_next;
};
struct mountres3_ok {
fhandle3 fhandle;
int auth_flavors<>;
};
union mountres3 switch (mountstat3 fhs_status) {
case MNT3_OK:
mountres3_ok mountinfo;
default:
void;
};
program MOUNT_PROGRAM {
version MOUNT_V3 {
void MOUNT3_NULL(void) = 0;
mountres3 MOUNT3_MNT(dirpath) = 1;
mountlist MOUNT3_DUMP(void) = 2;
void MOUNT3_UMNT(dirpath) = 3;
void MOUNT3_UMNTALL(void) = 4;
exports MOUNT3_EXPORT(void) = 5;
} = 3;
} = 100005;
This diff is collapsed.
This diff is collapsed.
/*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <errno.h>
#include <rpc/xdr.h>
#include "libnfs.h"
#include "libnfs-raw.h"
#include "libnfs-private.h"
#include "libnfs-raw-nfsacl.h"
int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
{
struct rpc_pdu *pdu;
pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_NULL, cb, private_data, (xdrproc_t)xdr_void, 0);
if (pdu == NULL) {
rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/null call");
return -1;
}
if (rpc_queue_pdu(rpc, pdu) != 0) {
rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/null call");
rpc_free_pdu(rpc, pdu);
return -2;
}
return 0;
}
/* deducted from wireshark traces */
program NFSACL_PROGRAM {
version NFSACL_V3 {
void NFSACL3_NULL(void) = 0;
} = 3;
} = 100227;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* From RFC1833
*/
const PMAP_PORT = 111; /* portmapper port number */
struct mapping {
unsigned int prog;
unsigned int vers;
unsigned int prot;
unsigned int port;
};
struct call_args {
unsigned int prog;
unsigned int vers;
unsigned int proc;
opaque args<>;
};
program PMAP_PROGRAM {
version PMAP_V2 {
void
PMAP_NULL(void) = 0;
bool
PMAP_SET(mapping) = 1;
bool
PMAP_UNSET(mapping) = 2;
unsigned int
PMAP_GETPORT(mapping) = 3;
} = 2;
} = 100000;
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment