6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
23 #define NFSD_PORTS_FILE "/proc/fs/nfsd/portlist"
24 #define NFSD_VERS_FILE "/proc/fs/nfsd/versions"
25 #define NFSD_THREAD_FILE "/proc/fs/nfsd/threads"
28 * declaring a common static scratch buffer here keeps us from having to
29 * continually thrash the stack. The value of 128 bytes here is really just a
30 * SWAG and can be increased if necessary. It ought to be enough for the
31 * routines below however.
36 * Are there already sockets configured? If not, then it is safe to try to
37 * open some and pass them through.
39 * Note: If the user explicitly asked for 'udp', then we should probably check
40 * if that is open, and should open it if not. However we don't yet. All
41 * sockets have to be opened when the first daemon is started.
48 fd = open(NFSD_PORTS_FILE, O_RDONLY);
50 /* problem opening file, assume that nothing is configured */
54 n = read(fd, buf, sizeof(buf));
57 xlog(D_GENERAL, "knfsd is currently %s", (n > 0) ? "up" : "down");
63 nfssvc_setfds(int port, unsigned int ctlbits, char *haddr)
66 int udpfd = -1, tcpfd = -1;
67 struct sockaddr_in sin;
72 fd = open(NFSD_PORTS_FILE, O_WRONLY);
75 sin.sin_family = AF_INET;
76 sin.sin_port = htons(port);
77 sin.sin_addr.s_addr = inet_addr(haddr);
79 if (NFSCTL_UDPISSET(ctlbits)) {
80 udpfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
82 xlog(L_ERROR, "unable to create UDP socket: "
83 "errno %d (%m)", errno);
86 if (bind(udpfd, (struct sockaddr *)&sin, sizeof(sin)) < 0){
87 xlog(L_ERROR, "unable to bind UDP socket: "
88 "errno %d (%m)", errno);
93 if (NFSCTL_TCPISSET(ctlbits)) {
94 tcpfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
96 xlog(L_ERROR, "unable to create TCP socket: "
97 "errno %d (%m)", errno);
100 if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
101 xlog(L_ERROR, "unable to set SO_REUSEADDR: "
102 "errno %d (%m)", errno);
105 if (bind(tcpfd, (struct sockaddr *)&sin, sizeof(sin)) < 0){
106 xlog(L_ERROR, "unable to bind TCP socket: "
107 "errno %d (%m)", errno);
110 if (listen(tcpfd, 64) < 0){
111 xlog(L_ERROR, "unable to create listening socket: "
112 "errno %d (%m)", errno);
117 snprintf(buf, sizeof(buf), "%d\n", udpfd);
118 if (write(fd, buf, strlen(buf)) != strlen(buf)) {
120 "writing fds to kernel failed: errno %d (%m)",
128 fd = open(NFSD_PORTS_FILE, O_WRONLY);
129 snprintf(buf, sizeof(buf), "%d\n", tcpfd);
130 if (write(fd, buf, strlen(buf)) != strlen(buf)) {
132 "writing fds to kernel failed: errno %d (%m)",
141 nfssvc_versbits(unsigned int ctlbits, int minorvers4)
148 fd = open(NFSD_VERS_FILE, O_WRONLY);
152 for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) {
153 if (NFSCTL_VERISSET(ctlbits, n))
154 off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n);
156 off += snprintf(ptr+off, sizeof(buf) - off, "-%d ", n);
158 n = minorvers4 >= 0 ? minorvers4 : -minorvers4;
159 if (n >= NFSD_MINMINORVERS4 && n <= NFSD_MAXMINORVERS4)
160 off += snprintf(ptr+off, sizeof(buf) - off, "%c4.%d",
161 minorvers4 > 0 ? '+' : '-',
163 xlog(D_GENERAL, "Writing version string to kernel: %s", buf);
164 snprintf(ptr+off, sizeof(buf) - off, "\n");
165 if (write(fd, buf, strlen(buf)) != strlen(buf))
166 xlog(L_ERROR, "Setting version failed: errno %d (%m)", errno);
173 nfssvc(int port, int nrservs, unsigned int versbits, int minorvers4,
174 unsigned protobits, char *haddr)
176 struct nfsctl_arg arg;
179 /* Note: must set versions before fds so that
180 * the ports get registered with portmap against correct
183 nfssvc_versbits(versbits, minorvers4);
184 nfssvc_setfds(port, protobits, haddr);
186 fd = open(NFSD_THREAD_FILE, O_WRONLY);
188 fd = open("/proc/fs/nfs/threads", O_WRONLY);
190 /* 2.5+ kernel with nfsd filesystem mounted.
191 * Just write the number in.
192 * Cannot handle port number yet, but does anyone care?
195 snprintf(buf, sizeof(buf), "%d\n", nrservs);
196 n = write(fd, buf, strlen(buf));
198 if (n != strlen(buf))
204 arg.ca_version = NFSCTL_VERSION;
205 arg.ca_svc.svc_nthreads = nrservs;
206 arg.ca_svc.svc_port = port;
207 return nfsctl(NFSCTL_SVC, &arg, NULL);