Break up the portmap spoofer into a bind function and a listen
function, so we can call the bind function before forking. Also,
waitpid() at the end so we don't make zombies.
diff --git a/nfsmount/dummypmap.c b/nfsmount/dummypmap.c
index adf64c9..0a900ca 100644
--- a/nfsmount/dummypmap.c
+++ b/nfsmount/dummypmap.c
@@ -34,18 +34,10 @@
__u32 port;
};
-FILE *portmap_file = 0;
-
-int dummy_portmap(void)
+int bind_portmap(void)
{
int sock = socket(PF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sin;
- int pktlen, addrlen;
- union {
- struct portmap_call c;
- unsigned char b[65536]; /* Max UDP packet size */
- } pkt;
- struct portmap_reply rply;
if ( sock < 0 )
return -1;
@@ -61,6 +53,19 @@
return -1;
}
+ return sock;
+}
+
+int dummy_portmap(int sock, FILE *portmap_file)
+{
+ struct sockaddr_in sin;
+ int pktlen, addrlen;
+ union {
+ struct portmap_call c;
+ unsigned char b[65536]; /* Max UDP packet size */
+ } pkt;
+ struct portmap_reply rply;
+
for(;;) {
addrlen = sizeof sin;
pktlen = recvfrom(sock, &pkt.c.rpc.hdr.udp, sizeof pkt, 0,
diff --git a/nfsmount/dummypmap.h b/nfsmount/dummypmap.h
index 2625133..b67ed19 100644
--- a/nfsmount/dummypmap.h
+++ b/nfsmount/dummypmap.h
@@ -6,6 +6,6 @@
#include <stdio.h>
-extern FILE *portmap_file;
-int dummy_portmap(void);
+int bind_portmap(void);
+int dummy_portmap(int sock, FILE *portmap_file);
diff --git a/nfsmount/main.c b/nfsmount/main.c
index c5eae47..a50d13c 100644
--- a/nfsmount/main.c
+++ b/nfsmount/main.c
@@ -164,6 +164,7 @@
char *path;
int c;
int spoof_portmap = 0;
+ FILE *portmap_file = NULL;
progname = argv[0];
@@ -221,14 +222,30 @@
check_path(path);
if ( spoof_portmap ) {
- spoof_portmap = fork();
- if ( spoof_portmap == -1 ) {
- fprintf(stderr, "%s: cannot fork\n", progname);
- exit(1);
- } else if ( spoof_portmap == 0 ) {
- /* Child process */
- dummy_portmap();
- _exit(255); /* Error */
+ int sock = bind_portmap();
+
+ if ( sock == -1 ) {
+ if ( errno == EINVAL || errno == EADDRINUSE )
+ spoof_portmap = 0; /* Assume not needed */
+ else {
+ fprintf(stderr,
+ "%s: portmap spoofing failed\n",
+ progname);
+ exit(1);
+ }
+ } else {
+ spoof_portmap = fork();
+ if ( spoof_portmap == -1 ) {
+ fprintf(stderr, "%s: cannot fork\n", progname);
+ exit(1);
+ } else if ( spoof_portmap == 0 ) {
+ /* Child process */
+ dummy_portmap(sock, portmap_file);
+ _exit(255); /* Error */
+ } else {
+ /* Parent process */
+ close(sock);
+ }
}
}
@@ -237,8 +254,11 @@
return 1;
/* If we set up the spoofer, tear it down now */
- if ( spoof_portmap )
+ if ( spoof_portmap ) {
kill(SIGTERM, spoof_portmap);
+ while ( waitpid(spoof_portmap, NULL, 0) == -1 &&
+ errno == EINTR );
+ }
free(rem_name);