Unix Technical Forum

[PATCH] mountd to listen to specified port

This is a discussion on [PATCH] mountd to listen to specified port within the mailing.openbsd.tech forums, part of the OpenBSD category; --> Hi tech@ I face a problem while triying to setup NFS server for clients behind my firewall. I wanted ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 09:26 AM
Alexey Vatchenko
 
Posts: n/a
Default [PATCH] mountd to listen to specified port

Hi tech@

I face a problem while triying to setup NFS server for clients behind my
firewall. I wanted to permit access only to certain ports not to all reserved
range.
So, i added -p flag to mountd. FreeBSD already has this flag, but my patch is
not based on their patch.

I added two supplimentary functions to lib/libc/rpc:
svctcp_create2 and svcudp_create2
(these functions allow us to add IPv6 support to mountd also)

Man pages are updated accordingly.

--
Alexey Vatchenko
http://www.bsdua.org
E-mail: avv@mail.zp.ua
JID: alex.vatchenko@gmail.com


Index: include/rpc/svc.h
================================================== =================
RCS file: /cvs/openbsd/src/include/rpc/svc.h,v
retrieving revision 1.9
diff -u -u -r1.9 svc.h
--- include/rpc/svc.h 22 Jan 2004 21:48:02 -0000 1.9
+++ include/rpc/svc.h 12 Jun 2007 07:06:33 -0000
@@ -305,6 +305,9 @@
__BEGIN_DECLS
extern SVCXPRT *svcudp_create(int);
extern SVCXPRT *svcudp_bufcreate(int, unsigned int, unsigned int);
+extern SVCXPRT *svcudp_create2(int, int, u_short);
+extern SVCXPRT *svcudp_bufcreate2(int, int, u_short, unsigned int,
+ unsigned int);
__END_DECLS


@@ -313,6 +316,7 @@
*/
__BEGIN_DECLS
extern SVCXPRT *svctcp_create(int, unsigned int, unsigned int);
+extern SVCXPRT *svctcp_create2(int, int, u_short, unsigned int, unsigned int);
__END_DECLS

/*
Index: lib/libc/rpc/rpc.3
================================================== =================
RCS file: /cvs/openbsd/src/lib/libc/rpc/rpc.3,v
retrieving revision 1.38
diff -u -u -r1.38 rpc.3
--- lib/libc/rpc/rpc.3 31 May 2007 19:19:30 -0000 1.38
+++ lib/libc/rpc/rpc.3 12 Jun 2007 07:06:36 -0000
@@ -78,7 +78,7 @@
.\" 2550 Garcia Avenue
.\" Mountain View, California 94043
.\"
-.Dd $Mdocdate$
+.Dd $Mdocdate: May 31 2007 $
.Dt RPC 3
.Os
.Sh NAME
@@ -134,7 +134,11 @@
.Nm svcerr_weakauth ,
.Nm svcfd_create ,
.Nm svctcp_create ,
+.Nm svctcp_create2 ,
.Nm svcudp_bufcreate ,
+.Nm svcudp_bufcreate2 ,
+.Nm svcudp_create ,
+.Nm svcudp_create2 ,
.Nm xdr_accepted_reply ,
.Nm xdr_authunix_parms ,
.Nm xdr_callhdr ,
@@ -259,9 +263,17 @@
.Ft SVCXPRT *
.Fn svctcp_create "int sock" "u_int send_buf_size" "u_int recv_buf_size"
.Ft SVCXPRT *
+.Fn svctcp_create2 "int sock" "int family" "u_short port" "u_int send_buf_size" "u_int recv_buf_size"
+.Ft SVCXPRT *
.Fn svcfd_create "int fd" "u_int sendsize" "u_int recvsize"
.Ft SVCXPRT *
-.Fn svcudp_bufcreate "int sock"
+.Fn svcudp_bufcreate "int sock" "u_int send_buf_size" "u_int recv_buf_size"
+.Ft SVCXPRT *
+.Fn svcudp_bufcreate2 "int sock" "int family" "u_short port" "u_int send_buf_size" "u_int recv_buf_size"
+.Ft SVCXPRT *
+.Fn svcudp_create "int sock"
+.Ft SVCXPRT *
+.Fn svcudp_create2 "int sock" "int family" "u_short port"
.Ft bool_t
.Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar"
.Ft bool_t
@@ -1227,6 +1239,13 @@
users may specify the size of buffers; values of zero
choose suitable defaults.
.Pp
+.Fn svctcp_create2
+supersedes
+.Fn svctcp_create
+function. It allows to specify address family and port number also. This
+function accepts AF_INET and AF_INET6 address families. If port is equal to 0,
+the function tries to bind socket to one of reserved ports.
+.Pp
.Fn svcfd_create
will create a service on top of any open descriptor.
Typically, this descriptor is a connected socket for a stream protocol such
@@ -1265,6 +1284,13 @@
.Tn UDP-based
.Tn RPC
messages.
+.Pp
+.Fn svcudp_bufcreate2
+supersedes
+.Fn svcudp_bufcreate
+function. It allows to specify address family and port number also. This
+function accepts AF_INET and AF_INET6 address families. If port is equal to 0,
+the function tries to bind socket to one of reserved ports.
.Pp
.Fn xdr_accepted_reply
is used for encoding
Index: lib/libc/rpc/svc_tcp.c
================================================== =================
RCS file: /cvs/openbsd/src/lib/libc/rpc/svc_tcp.c,v
retrieving revision 1.28
diff -u -u -r1.28 svc_tcp.c
--- lib/libc/rpc/svc_tcp.c 2 Apr 2006 00:36:05 -0000 1.28
+++ lib/libc/rpc/svc_tcp.c 12 Jun 2007 07:06:36 -0000
@@ -135,7 +135,7 @@

if (sock == RPC_ANYSOCK) {
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- perror("svctcp_.c - udp socket creation problem");
+ perror("svctcp_.c - tcp socket creation problem");
return (NULL);
}
madesock = TRUE;
@@ -185,6 +185,119 @@
return (NULL);
}
return (xprt);
+}
+
+/*
+ * This function creates sock (with specified adress family) if sock is -1.
+ * Then binds it to the specified port. It's possible to create v4 and v6
+ * sockets.
+ */
+SVCXPRT *
+svctcp_create2(int sock, int af, u_short port, u_int sendsize, u_int recvsize)
+{
+ struct tcp_rendezvous *r;
+ SVCXPRT *xprt;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+ socklen_t salen;
+ bool_t madesock;
+ int error;
+
+#ifdef INET6
+ if (af != AF_INET && af != AF_INET6)
+ return (NULL);
+#else
+ if (af != AF_INET)
+ return (NULL);
+#endif
+
+ madesock = FALSE;
+
+ if (sock == RPC_ANYSOCK) {
+ sock = socket(af, SOCK_STREAM, 0);
+ if (sock == -1)
+ return (NULL);
+ madesock = TRUE;
+ }
+
+ if (af == AF_INET) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+ salen = sizeof(sin);
+ sa = (struct sockaddr *)&sin;
+ }
+#ifdef INET6
+ else {
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin_family = AF_INET6;
+ sin6.sin_port = htons(port);
+ sin6.sin_addr.s_addr = in6addr_any;
+ salen = sizeof(sin6);
+ sa = (struct sockaddr *)&sin6;
+ }
+#endif /* INET6 */
+
+ switch (port) {
+ case 0:
+ error = bindresvport_sa(sock, sa);
+ if (error == 0)
+ break;
+ /* FALLTHOUGH */
+ default:
+ error = bind(sock, sa, salen);
+ break;
+ }
+
+ if (error != 0 || listen(sock, 2) != 0) {
+ if (madesock)
+ close(sock);
+ return (NULL);
+ }
+
+ if (port == 0) {
+ if (getsockname(sock, sa, &salen) != 0) {
+ if (madesock)
+ close(sock);
+ return (NULL);
+ }
+ if (af == AF_INET)
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+#ifdef INET6
+ else
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin_port);
+#endif
+ }
+
+ r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
+ if (r != NULL) {
+ r->sendsize = sendsize;
+ r->recvsize = recvsize;
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt != NULL) {
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)r;
+ xprt->xp_verf = _null_auth;
+ xprt->xp_ops = &svctcp_rendezvous_op;
+ xprt->xp_port = port;
+ xprt->xp_sock = sock;
+ if (__xprt_register(xprt) != 0)
+ return (xprt);
+
+ free(xprt);
+ }
+ free(r);
+ }
+
+ if (madesock)
+ close(sock);
+
+ return (NULL);
}

/*
Index: lib/libc/rpc/svc_udp.c
================================================== =================
RCS file: /cvs/openbsd/src/lib/libc/rpc/svc_udp.c,v
retrieving revision 1.16
diff -u -u -r1.16 svc_udp.c
--- lib/libc/rpc/svc_udp.c 8 Aug 2005 08:05:35 -0000 1.16
+++ lib/libc/rpc/svc_udp.c 12 Jun 2007 07:06:36 -0000
@@ -171,6 +171,125 @@
return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
}

+SVCXPRT *
+svcudp_bufcreate2(int sock, int af, u_short port, u_int sendsz, u_int recvsz)
+{
+ SVCXPRT *xprt;
+ struct svcudp_data *su;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+ socklen_t salen;
+ bool_t madesock;
+ int error;
+
+#ifdef INET6
+ if (af != AF_INET && af != AF_INET6)
+ return (NULL);
+#else
+ if (af != AF_INET)
+ return (NULL);
+#endif
+
+ madesock = FALSE;
+
+ if (sock == RPC_ANYSOCK) {
+ sock = socket(af, SOCK_DGRAM, 0);
+ if (sock == -1)
+ return (NULL);
+ madesock = TRUE;
+ }
+
+ if (af == AF_INET) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+ salen = sizeof(sin);
+ sa = (struct sockaddr *)&sin;
+ }
+#ifdef INET6
+ else {
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin_family = AF_INET6;
+ sin6.sin_port = htons(port);
+ sin6.sin_addr.s_addr = in6addr_any;
+ salen = sizeof(sin6);
+ sa = (struct sockaddr *)&sin6;
+ }
+#endif /* INET6 */
+
+ switch (port) {
+ case 0:
+ error = bindresvport_sa(sock, sa);
+ if (error == 0)
+ break;
+ /* FALLTHOUGH */
+ default:
+ error = bind(sock, sa, salen);
+ break;
+ }
+
+ if (error != 0) {
+ if (madesock)
+ close(sock);
+ return (NULL);
+ }
+
+ if (port == 0) {
+ if (getsockname(sock, sa, &salen) != 0) {
+ if (madesock)
+ close(sock);
+ return (NULL);
+ }
+ if (af == AF_INET)
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+#ifdef INET6
+ else
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin_port);
+#endif
+ }
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(*xprt));
+ if (xprt != NULL) {
+ su = (struct svcudp_data *)mem_alloc(sizeof(*su));
+ if (su != NULL) {
+ su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
+ rpc_buffer(xprt) = mem_alloc(su->su_iosz);
+ if (rpc_buffer(xprt) != NULL) {
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt),
+ su->su_iosz, XDR_DECODE);
+ su->su_cache = NULL;
+ xprt->xp_p2 = (caddr_t)su;
+ xprt->xp_verf.oa_base = su->su_verfbody;
+ xprt->xp_ops = &svcudp_op;
+ xprt->xp_port = port;
+ xprt->xp_sock = sock;
+
+ if (__xprt_register(xprt) != 0)
+ return (xprt);
+
+ free(rpc_buffer(xprt));
+ }
+ free(su);
+ }
+ free(xprt);
+ }
+
+ if (madesock)
+ close(sock);
+ return (NULL);
+}
+
+SVCXPRT *
+svcudp_create2(int sock, int af, u_short port)
+{
+
+ return(svcudp_bufcreate2(sock, af, port, UDPMSGSIZE, UDPMSGSIZE));
+}
+
/* ARGSUSED */
static enum xprt_stat
svcudp_stat(SVCXPRT *xprt)
Index: sbin/mountd/mountd.8
================================================== =================
RCS file: /cvs/openbsd/src/sbin/mountd/mountd.8,v
retrieving revision 1.16
diff -u -u -r1.16 mountd.8
--- sbin/mountd/mountd.8 31 May 2007 19:19:46 -0000 1.16
+++ sbin/mountd/mountd.8 12 Jun 2007 07:06:44 -0000
@@ -30,7 +30,7 @@
.\"
.\" @(#)mountd.8 8.4 (Berkeley) 4/28/95
.\"
-.Dd $Mdocdate$
+.Dd $Mdocdate: May 31 2007 $
.Dt MOUNTD 8
.Os
.Sh NAME
@@ -41,6 +41,7 @@
.Sh SYNOPSIS
.Nm mountd
.Op Fl dn
+.Op Fl p Ar portnum
.Op Ar exportsfile
.Sh DESCRIPTION
.Nm
@@ -71,6 +72,10 @@
The use of
.Fl n
is STRONGLY discouraged, as it opens up a wide range of security problems.
+.It Fl p Ar portnum
+Specify port number
+.Nm
+will listen on. It allows to configure firewall to filter on this port.
.It Ar exportsfile
The
.Ar exportsfile
Index: sbin/mountd/mountd.c
================================================== =================
RCS file: /cvs/openbsd/src/sbin/mountd/mountd.c,v
retrieving revision 1.68
diff -u -u -r1.68 mountd.c
--- sbin/mountd/mountd.c 1 Jun 2007 05:37:14 -0000 1.68
+++ sbin/mountd/mountd.c 12 Jun 2007 07:06:45 -0000
@@ -65,6 +65,7 @@
#include <arpa/inet.h>

#include <ctype.h>
+#include <err.h>
#include <errno.h>
#include <grp.h>
#include <netdb.h>
@@ -189,6 +190,8 @@
int xdr_mlist(XDR *, caddr_t);
void mountd_svc_run(void);

+SVCXPRT * create_svctcp(u_short port, int af);
+
struct exportlist *exphead;
struct mountlist *mlhead;
struct grouplist *grphead;
@@ -210,6 +213,7 @@
#define OP_ALLDIRS 0x40

int debug = 0;
+u_short use_port = 0; /* default: any */

volatile sig_atomic_t gothup;
volatile sig_atomic_t gotterm;
@@ -228,8 +232,11 @@
SVCXPRT *udptransp, *tcptransp;
FILE *pidfile;
int c;
+ char *errstr;
+ long long portnum;

- while ((c = getopt(argc, argv, "dnr")) != -1)
+ portnum = 0; /* any port */
+ while ((c = getopt(argc, argv, "dnrp:")) != -1)
switch (c) {
case 'd':
debug = 1;
@@ -240,8 +247,15 @@
case 'r':
/* Compatibility */
break;
+ case 'p':
+ portnum = strtonum(optarg, 0, USHRT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "Port number is invalid");
+ use_port = portnum;
+ break;
default:
- fprintf(stderr, "Usage: mountd [-dn] [export_file]\n");
+ fprintf(stderr,
+ "Usage: mountd [-dn] [-p port] [export_file]\n");
exit(1);
}
argc -= optind;
@@ -287,8 +301,8 @@
signal(SIGHUP, (void (*)(int)) new_exportlist);
signal(SIGTERM, (void (*)(int)) send_umntall);
signal(SIGSYS, SIG_IGN);
- if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL ||
- (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) {
+ if ((udptransp = svcudp_create2(RPC_ANYSOCK, AF_INET, portnum)) == NULL ||
+ (tcptransp = svctcp_create2(RPC_ANYSOCK, AF_INET, portnum, 0, 0)) == NULL) {
syslog(LOG_ERR, "Can't create socket");
exit(1);
}

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 08:48 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com