xref: /freebsd/sys/rpc/rpc_generic.c (revision 10f0bcab61ef441cb5af32fb706688d8cbd55dc0)
1 /*	$NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $	*/
2 
3 /*
4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5  * unrestricted use provided that this legend is included on all tape
6  * media and as a part of the software program in whole or part.  Users
7  * may copy or modify Sun RPC without charge, but are not authorized
8  * to license or distribute it to anyone else except as part of a product or
9  * program developed by the user.
10  *
11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14  *
15  * Sun RPC is provided with no support and without any obligation on the
16  * part of Sun Microsystems, Inc. to assist in its use, correction,
17  * modification or enhancement.
18  *
19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21  * OR ANY PART THEREOF.
22  *
23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24  * or profits or other special, indirect and consequential damages, even if
25  * Sun has been advised of the possibility of such damages.
26  *
27  * Sun Microsystems, Inc.
28  * 2550 Garcia Avenue
29  * Mountain View, California  94043
30  */
31 /*
32  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
33  */
34 
35 /* #pragma ident	"@(#)rpc_generic.c	1.17	94/04/24 SMI" */
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 /*
40  * rpc_generic.c, Miscl routines for RPC.
41  *
42  */
43 
44 #include "opt_inet6.h"
45 
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/module.h>
50 #include <sys/proc.h>
51 #include <sys/protosw.h>
52 #include <sys/sbuf.h>
53 #include <sys/systm.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/syslog.h>
57 
58 #include <rpc/rpc.h>
59 #include <rpc/nettype.h>
60 
61 #include "rpc_com.h"
62 
63 struct handle {
64 	NCONF_HANDLE *nhandle;
65 	int nflag;		/* Whether NETPATH or NETCONFIG */
66 	int nettype;
67 };
68 
69 static const struct _rpcnettype {
70 	const char *name;
71 	const int type;
72 } _rpctypelist[] = {
73 	{ "netpath", _RPC_NETPATH },
74 	{ "visible", _RPC_VISIBLE },
75 	{ "circuit_v", _RPC_CIRCUIT_V },
76 	{ "datagram_v", _RPC_DATAGRAM_V },
77 	{ "circuit_n", _RPC_CIRCUIT_N },
78 	{ "datagram_n", _RPC_DATAGRAM_N },
79 	{ "tcp", _RPC_TCP },
80 	{ "udp", _RPC_UDP },
81 	{ 0, _RPC_NONE }
82 };
83 
84 struct netid_af {
85 	const char	*netid;
86 	int		af;
87 	int		protocol;
88 };
89 
90 static const struct netid_af na_cvt[] = {
91 	{ "udp",  AF_INET,  IPPROTO_UDP },
92 	{ "tcp",  AF_INET,  IPPROTO_TCP },
93 #ifdef INET6
94 	{ "udp6", AF_INET6, IPPROTO_UDP },
95 	{ "tcp6", AF_INET6, IPPROTO_TCP },
96 #endif
97 	{ "local", AF_LOCAL, 0 }
98 };
99 
100 struct rpc_createerr rpc_createerr;
101 
102 /*
103  * Find the appropriate buffer size
104  */
105 u_int
106 /*ARGSUSED*/
107 __rpc_get_t_size(int af, int proto, int size)
108 {
109 	int maxsize, defsize;
110 
111 	maxsize = 256 * 1024;	/* XXX */
112 	switch (proto) {
113 	case IPPROTO_TCP:
114 		defsize = 64 * 1024;	/* XXX */
115 		break;
116 	case IPPROTO_UDP:
117 		defsize = UDPMSGSIZE;
118 		break;
119 	default:
120 		defsize = RPC_MAXDATASIZE;
121 		break;
122 	}
123 	if (size == 0)
124 		return defsize;
125 
126 	/* Check whether the value is within the upper max limit */
127 	return (size > maxsize ? (u_int)maxsize : (u_int)size);
128 }
129 
130 /*
131  * Find the appropriate address buffer size
132  */
133 u_int
134 __rpc_get_a_size(af)
135 	int af;
136 {
137 	switch (af) {
138 	case AF_INET:
139 		return sizeof (struct sockaddr_in);
140 #ifdef INET6
141 	case AF_INET6:
142 		return sizeof (struct sockaddr_in6);
143 #endif
144 	case AF_LOCAL:
145 		return sizeof (struct sockaddr_un);
146 	default:
147 		break;
148 	}
149 	return ((u_int)RPC_MAXADDRSIZE);
150 }
151 
152 #if 0
153 
154 /*
155  * Used to ping the NULL procedure for clnt handle.
156  * Returns NULL if fails, else a non-NULL pointer.
157  */
158 void *
159 rpc_nullproc(clnt)
160 	CLIENT *clnt;
161 {
162 	struct timeval TIMEOUT = {25, 0};
163 
164 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
165 		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
166 		return (NULL);
167 	}
168 	return ((void *) clnt);
169 }
170 
171 #endif
172 
173 int
174 __rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip)
175 {
176 	int type, proto;
177 	struct sockaddr *sa;
178 	sa_family_t family;
179 	struct sockopt opt;
180 	int error;
181 
182 	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
183 	if (error)
184 		return 0;
185 
186 	sip->si_alen = sa->sa_len;
187 	family = sa->sa_family;
188 	free(sa, M_SONAME);
189 
190 	opt.sopt_dir = SOPT_GET;
191 	opt.sopt_level = SOL_SOCKET;
192 	opt.sopt_name = SO_TYPE;
193 	opt.sopt_val = &type;
194 	opt.sopt_valsize = sizeof type;
195 	opt.sopt_td = NULL;
196 	error = sogetopt(so, &opt);
197 	if (error)
198 		return 0;
199 
200 	/* XXX */
201 	if (family != AF_LOCAL) {
202 		if (type == SOCK_STREAM)
203 			proto = IPPROTO_TCP;
204 		else if (type == SOCK_DGRAM)
205 			proto = IPPROTO_UDP;
206 		else
207 			return 0;
208 	} else
209 		proto = 0;
210 
211 	sip->si_af = family;
212 	sip->si_proto = proto;
213 	sip->si_socktype = type;
214 
215 	return 1;
216 }
217 
218 /*
219  * Linear search, but the number of entries is small.
220  */
221 int
222 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
223 {
224 	int i;
225 
226 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
227 		if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
228 		    strcmp(nconf->nc_netid, "unix") == 0 &&
229 		    strcmp(na_cvt[i].netid, "local") == 0)) {
230 			sip->si_af = na_cvt[i].af;
231 			sip->si_proto = na_cvt[i].protocol;
232 			sip->si_socktype =
233 			    __rpc_seman2socktype((int)nconf->nc_semantics);
234 			if (sip->si_socktype == -1)
235 				return 0;
236 			sip->si_alen = __rpc_get_a_size(sip->si_af);
237 			return 1;
238 		}
239 
240 	return 0;
241 }
242 
243 struct socket *
244 __rpc_nconf2socket(const struct netconfig *nconf)
245 {
246 	struct __rpc_sockinfo si;
247 	struct socket *so;
248 	int error;
249 
250 	if (!__rpc_nconf2sockinfo(nconf, &si))
251 		return 0;
252 
253 	so = NULL;
254 	error =  socreate(si.si_af, &so, si.si_socktype, si.si_proto,
255 	    curthread->td_ucred, curthread);
256 
257 	if (error)
258 		return NULL;
259 	else
260 		return so;
261 }
262 
263 char *
264 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
265 {
266 	struct __rpc_sockinfo si;
267 
268 	if (!__rpc_nconf2sockinfo(nconf, &si))
269 		return NULL;
270 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
271 }
272 
273 struct netbuf *
274 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
275 {
276 	struct __rpc_sockinfo si;
277 
278 	if (!__rpc_nconf2sockinfo(nconf, &si))
279 		return NULL;
280 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
281 }
282 
283 char *
284 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
285 {
286 	char *ret;
287 	struct sbuf sb;
288 	struct sockaddr_in *sin;
289 	struct sockaddr_un *sun;
290 	char namebuf[INET_ADDRSTRLEN];
291 #ifdef INET6
292 	struct sockaddr_in6 *sin6;
293 	char namebuf6[INET6_ADDRSTRLEN];
294 #endif
295 	u_int16_t port;
296 
297 	sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND);
298 
299 	switch (af) {
300 	case AF_INET:
301 		sin = nbuf->buf;
302 		if (__rpc_inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
303 		    == NULL)
304 			return NULL;
305 		port = ntohs(sin->sin_port);
306 		if (sbuf_printf(&sb, "%s.%u.%u", namebuf,
307 			((uint32_t)port) >> 8,
308 			port & 0xff) < 0)
309 			return NULL;
310 		break;
311 #ifdef INET6
312 	case AF_INET6:
313 		sin6 = nbuf->buf;
314 		if (__rpc_inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
315 		    == NULL)
316 			return NULL;
317 		port = ntohs(sin6->sin6_port);
318 		if (sbuf_printf(&sb, "%s.%u.%u", namebuf6,
319 			((uint32_t)port) >> 8,
320 			port & 0xff) < 0)
321 			return NULL;
322 		break;
323 #endif
324 	case AF_LOCAL:
325 		sun = nbuf->buf;
326 		if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len -
327 			    offsetof(struct sockaddr_un, sun_path)),
328 			sun->sun_path) < 0)
329 			return (NULL);
330 		break;
331 	default:
332 		return NULL;
333 	}
334 
335 	sbuf_finish(&sb);
336 	ret = strdup(sbuf_data(&sb), M_RPC);
337 	sbuf_delete(&sb);
338 
339 	return ret;
340 }
341 
342 struct netbuf *
343 __rpc_uaddr2taddr_af(int af, const char *uaddr)
344 {
345 	struct netbuf *ret = NULL;
346 	char *addrstr, *p;
347 	unsigned port, portlo, porthi;
348 	struct sockaddr_in *sin;
349 #ifdef INET6
350 	struct sockaddr_in6 *sin6;
351 #endif
352 	struct sockaddr_un *sun;
353 
354 	port = 0;
355 	sin = NULL;
356 	addrstr = strdup(uaddr, M_RPC);
357 	if (addrstr == NULL)
358 		return NULL;
359 
360 	/*
361 	 * AF_LOCAL addresses are expected to be absolute
362 	 * pathnames, anything else will be AF_INET or AF_INET6.
363 	 */
364 	if (*addrstr != '/') {
365 		p = strrchr(addrstr, '.');
366 		if (p == NULL)
367 			goto out;
368 		portlo = (unsigned)strtol(p + 1, NULL, 10);
369 		*p = '\0';
370 
371 		p = strrchr(addrstr, '.');
372 		if (p == NULL)
373 			goto out;
374 		porthi = (unsigned)strtol(p + 1, NULL, 10);
375 		*p = '\0';
376 		port = (porthi << 8) | portlo;
377 	}
378 
379 	ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
380 	if (ret == NULL)
381 		goto out;
382 
383 	switch (af) {
384 	case AF_INET:
385 		sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
386 		    M_WAITOK);
387 		if (sin == NULL)
388 			goto out;
389 		memset(sin, 0, sizeof *sin);
390 		sin->sin_family = AF_INET;
391 		sin->sin_port = htons(port);
392 		if (__rpc_inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
393 			free(sin, M_RPC);
394 			free(ret, M_RPC);
395 			ret = NULL;
396 			goto out;
397 		}
398 		sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
399 		ret->buf = sin;
400 		break;
401 #ifdef INET6
402 	case AF_INET6:
403 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
404 		    M_WAITOK);
405 		if (sin6 == NULL)
406 			goto out;
407 		memset(sin6, 0, sizeof *sin6);
408 		sin6->sin6_family = AF_INET6;
409 		sin6->sin6_port = htons(port);
410 		if (__rpc_inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
411 			free(sin6, M_RPC);
412 			free(ret, M_RPC);
413 			ret = NULL;
414 			goto out;
415 		}
416 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
417 		ret->buf = sin6;
418 		break;
419 #endif
420 	case AF_LOCAL:
421 		sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
422 		    M_WAITOK);
423 		if (sun == NULL)
424 			goto out;
425 		memset(sun, 0, sizeof *sun);
426 		sun->sun_family = AF_LOCAL;
427 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
428 		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
429 		ret->buf = sun;
430 		break;
431 	default:
432 		break;
433 	}
434 out:
435 	free(addrstr, M_RPC);
436 	return ret;
437 }
438 
439 int
440 __rpc_seman2socktype(int semantics)
441 {
442 	switch (semantics) {
443 	case NC_TPI_CLTS:
444 		return SOCK_DGRAM;
445 	case NC_TPI_COTS_ORD:
446 		return SOCK_STREAM;
447 	case NC_TPI_RAW:
448 		return SOCK_RAW;
449 	default:
450 		break;
451 	}
452 
453 	return -1;
454 }
455 
456 int
457 __rpc_socktype2seman(int socktype)
458 {
459 	switch (socktype) {
460 	case SOCK_DGRAM:
461 		return NC_TPI_CLTS;
462 	case SOCK_STREAM:
463 		return NC_TPI_COTS_ORD;
464 	case SOCK_RAW:
465 		return NC_TPI_RAW;
466 	default:
467 		break;
468 	}
469 
470 	return -1;
471 }
472 
473 /*
474  * Returns the type of the network as defined in <rpc/nettype.h>
475  * If nettype is NULL, it defaults to NETPATH.
476  */
477 static int
478 getnettype(const char *nettype)
479 {
480 	int i;
481 
482 	if ((nettype == NULL) || (nettype[0] == 0)) {
483 		return (_RPC_NETPATH);	/* Default */
484 	}
485 
486 #if 0
487 	nettype = strlocase(nettype);
488 #endif
489 	for (i = 0; _rpctypelist[i].name; i++)
490 		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
491 			return (_rpctypelist[i].type);
492 		}
493 	return (_rpctypelist[i].type);
494 }
495 
496 /*
497  * For the given nettype (tcp or udp only), return the first structure found.
498  * This should be freed by calling freenetconfigent()
499  */
500 struct netconfig *
501 __rpc_getconfip(const char *nettype)
502 {
503 	char *netid;
504 	static char *netid_tcp = (char *) NULL;
505 	static char *netid_udp = (char *) NULL;
506 	struct netconfig *dummy;
507 
508 	if (!netid_udp && !netid_tcp) {
509 		struct netconfig *nconf;
510 		void *confighandle;
511 
512 		if (!(confighandle = setnetconfig())) {
513 			log(LOG_ERR, "rpc: failed to open " NETCONFIG);
514 			return (NULL);
515 		}
516 		while ((nconf = getnetconfig(confighandle)) != NULL) {
517 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
518 				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
519 					netid_tcp = strdup(nconf->nc_netid,
520 					    M_RPC);
521 				} else
522 				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
523 					netid_udp = strdup(nconf->nc_netid,
524 					    M_RPC);
525 				}
526 			}
527 		}
528 		endnetconfig(confighandle);
529 	}
530 	if (strcmp(nettype, "udp") == 0)
531 		netid = netid_udp;
532 	else if (strcmp(nettype, "tcp") == 0)
533 		netid = netid_tcp;
534 	else {
535 		return (NULL);
536 	}
537 	if ((netid == NULL) || (netid[0] == 0)) {
538 		return (NULL);
539 	}
540 	dummy = getnetconfigent(netid);
541 	return (dummy);
542 }
543 
544 /*
545  * Returns the type of the nettype, which should then be used with
546  * __rpc_getconf().
547  *
548  * For simplicity in the kernel, we don't support the NETPATH
549  * environment variable. We behave as userland would then NETPATH is
550  * unset, i.e. iterate over all visible entries in netconfig.
551  */
552 void *
553 __rpc_setconf(nettype)
554 	const char *nettype;
555 {
556 	struct handle *handle;
557 
558 	handle = (struct handle *) malloc(sizeof (struct handle),
559 	    M_RPC, M_WAITOK);
560 	switch (handle->nettype = getnettype(nettype)) {
561 	case _RPC_NETPATH:
562 	case _RPC_CIRCUIT_N:
563 	case _RPC_DATAGRAM_N:
564 		if (!(handle->nhandle = setnetconfig()))
565 			goto failed;
566 		handle->nflag = TRUE;
567 		break;
568 	case _RPC_VISIBLE:
569 	case _RPC_CIRCUIT_V:
570 	case _RPC_DATAGRAM_V:
571 	case _RPC_TCP:
572 	case _RPC_UDP:
573 		if (!(handle->nhandle = setnetconfig())) {
574 		        log(LOG_ERR, "rpc: failed to open " NETCONFIG);
575 			goto failed;
576 		}
577 		handle->nflag = FALSE;
578 		break;
579 	default:
580 		goto failed;
581 	}
582 
583 	return (handle);
584 
585 failed:
586 	free(handle, M_RPC);
587 	return (NULL);
588 }
589 
590 /*
591  * Returns the next netconfig struct for the given "net" type.
592  * __rpc_setconf() should have been called previously.
593  */
594 struct netconfig *
595 __rpc_getconf(void *vhandle)
596 {
597 	struct handle *handle;
598 	struct netconfig *nconf;
599 
600 	handle = (struct handle *)vhandle;
601 	if (handle == NULL) {
602 		return (NULL);
603 	}
604 	for (;;) {
605 		if (handle->nflag) {
606 			nconf = getnetconfig(handle->nhandle);
607 			if (nconf && !(nconf->nc_flag & NC_VISIBLE))
608 				continue;
609 		} else {
610 			nconf = getnetconfig(handle->nhandle);
611 		}
612 		if (nconf == NULL)
613 			break;
614 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
615 			(nconf->nc_semantics != NC_TPI_COTS) &&
616 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
617 			continue;
618 		switch (handle->nettype) {
619 		case _RPC_VISIBLE:
620 			if (!(nconf->nc_flag & NC_VISIBLE))
621 				continue;
622 			/* FALLTHROUGH */
623 		case _RPC_NETPATH:	/* Be happy */
624 			break;
625 		case _RPC_CIRCUIT_V:
626 			if (!(nconf->nc_flag & NC_VISIBLE))
627 				continue;
628 			/* FALLTHROUGH */
629 		case _RPC_CIRCUIT_N:
630 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
631 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
632 				continue;
633 			break;
634 		case _RPC_DATAGRAM_V:
635 			if (!(nconf->nc_flag & NC_VISIBLE))
636 				continue;
637 			/* FALLTHROUGH */
638 		case _RPC_DATAGRAM_N:
639 			if (nconf->nc_semantics != NC_TPI_CLTS)
640 				continue;
641 			break;
642 		case _RPC_TCP:
643 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
644 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
645 				(strcmp(nconf->nc_protofmly, NC_INET)
646 #ifdef INET6
647 				 && strcmp(nconf->nc_protofmly, NC_INET6))
648 #else
649 				)
650 #endif
651 				||
652 				strcmp(nconf->nc_proto, NC_TCP))
653 				continue;
654 			break;
655 		case _RPC_UDP:
656 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
657 				(strcmp(nconf->nc_protofmly, NC_INET)
658 #ifdef INET6
659 				&& strcmp(nconf->nc_protofmly, NC_INET6))
660 #else
661 				)
662 #endif
663 				||
664 				strcmp(nconf->nc_proto, NC_UDP))
665 				continue;
666 			break;
667 		}
668 		break;
669 	}
670 	return (nconf);
671 }
672 
673 void
674 __rpc_endconf(vhandle)
675 	void * vhandle;
676 {
677 	struct handle *handle;
678 
679 	handle = (struct handle *) vhandle;
680 	if (handle == NULL) {
681 		return;
682 	}
683 	endnetconfig(handle->nhandle);
684 	free(handle, M_RPC);
685 }
686 
687 int
688 __rpc_sockisbound(struct socket *so)
689 {
690 	struct sockaddr *sa;
691 	int error, bound;
692 
693 	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
694 	if (error)
695 		return (0);
696 
697 	switch (sa->sa_family) {
698 		case AF_INET:
699 			bound = (((struct sockaddr_in *) sa)->sin_port != 0);
700 			break;
701 #ifdef INET6
702 		case AF_INET6:
703 			bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0);
704 			break;
705 #endif
706 		case AF_LOCAL:
707 			/* XXX check this */
708 			bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0');
709 			break;
710 		default:
711 			bound = FALSE;
712 			break;
713 	}
714 
715 	free(sa, M_SONAME);
716 
717 	return bound;
718 }
719 
720 /*
721  * Kernel module glue
722  */
723 static int
724 krpc_modevent(module_t mod, int type, void *data)
725 {
726 
727 	return (0);
728 }
729 static moduledata_t krpc_mod = {
730 	"krpc",
731 	krpc_modevent,
732 	NULL,
733 };
734 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY);
735 
736 /* So that loader and kldload(2) can find us, wherever we are.. */
737 MODULE_VERSION(krpc, 1);
738