krpc_subr.c (b40ce4165d5eb3a5de1515245055350ae3dbab8e) | krpc_subr.c (7c208ed659437ef984f2bb98bdc20fa5cfdebefc) |
---|---|
1/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */ | 1/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */ |
2/* $FreeBSD$ */ | |
3 | 2 |
4/* | 3/*- |
5 * Copyright (c) 1995 Gordon Ross, Adam Glass 6 * Copyright (c) 1992 Regents of the University of California. 7 * All rights reserved. 8 * 9 * This software was developed by the Computer Systems Engineering group 10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 * contributed to Berkeley. 12 * --- 25 unchanged lines hidden (view full) --- 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * partially based on: 42 * libnetboot/rpc.c 43 * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) 44 */ 45 | 4 * Copyright (c) 1995 Gordon Ross, Adam Glass 5 * Copyright (c) 1992 Regents of the University of California. 6 * All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * --- 25 unchanged lines hidden (view full) --- 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * partially based on: 41 * libnetboot/rpc.c 42 * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) 43 */ 44 |
45#include <sys/cdefs.h> 46__FBSDID("$FreeBSD$"); 47 |
|
46#include <sys/param.h> 47#include <sys/systm.h> | 48#include <sys/param.h> 49#include <sys/systm.h> |
50#include <sys/jail.h> |
|
48#include <sys/malloc.h> 49#include <sys/mbuf.h> | 51#include <sys/malloc.h> 52#include <sys/mbuf.h> |
53#include <sys/proc.h> |
|
50#include <sys/socket.h> 51#include <sys/socketvar.h> 52#include <sys/uio.h> 53 54#include <net/if.h> | 54#include <sys/socket.h> 55#include <sys/socketvar.h> 56#include <sys/uio.h> 57 58#include <net/if.h> |
59#include <net/vnet.h> 60 |
|
55#include <netinet/in.h> 56 | 61#include <netinet/in.h> 62 |
57#include <nfs/rpcv2.h> | 63#include <rpc/types.h> 64#include <rpc/auth.h> 65#include <rpc/rpc_msg.h> |
58#include <nfs/krpc.h> 59#include <nfs/xdr_subs.h> 60 61/* 62 * Kernel support for Sun RPC 63 * 64 * Used currently for bootstrapping in nfs diskless configurations. 65 */ --- 10 unchanged lines hidden (view full) --- 76struct auth_unix { 77 int32_t ua_time; 78 int32_t ua_hostname; /* null */ 79 int32_t ua_uid; 80 int32_t ua_gid; 81 int32_t ua_gidlist; /* null */ 82}; 83 | 66#include <nfs/krpc.h> 67#include <nfs/xdr_subs.h> 68 69/* 70 * Kernel support for Sun RPC 71 * 72 * Used currently for bootstrapping in nfs diskless configurations. 73 */ --- 10 unchanged lines hidden (view full) --- 84struct auth_unix { 85 int32_t ua_time; 86 int32_t ua_hostname; /* null */ 87 int32_t ua_uid; 88 int32_t ua_gid; 89 int32_t ua_gidlist; /* null */ 90}; 91 |
84struct rpc_call { | 92struct krpc_call { |
85 u_int32_t rp_xid; /* request transaction id */ 86 int32_t rp_direction; /* call direction (0) */ 87 u_int32_t rp_rpcvers; /* rpc version (2) */ 88 u_int32_t rp_prog; /* program */ 89 u_int32_t rp_vers; /* version */ 90 u_int32_t rp_proc; /* procedure */ 91 struct auth_info rpc_auth; 92 struct auth_unix rpc_unix; 93 struct auth_info rpc_verf; 94}; 95 | 93 u_int32_t rp_xid; /* request transaction id */ 94 int32_t rp_direction; /* call direction (0) */ 95 u_int32_t rp_rpcvers; /* rpc version (2) */ 96 u_int32_t rp_prog; /* program */ 97 u_int32_t rp_vers; /* version */ 98 u_int32_t rp_proc; /* procedure */ 99 struct auth_info rpc_auth; 100 struct auth_unix rpc_unix; 101 struct auth_info rpc_verf; 102}; 103 |
96struct rpc_reply { | 104struct krpc_reply { |
97 u_int32_t rp_xid; /* request transaction id */ 98 int32_t rp_direction; /* call direction (1) */ 99 int32_t rp_astatus; /* accept status (0: accepted) */ 100 union { 101 u_int32_t rpu_errno; 102 struct { 103 struct auth_info rok_auth; 104 u_int32_t rok_status; --- 14 unchanged lines hidden (view full) --- 119 */ 120#define MAX_RESEND_DELAY 5 /* seconds */ 121 122/* 123 * Call portmap to lookup a port number for a particular rpc program 124 * Returns non-zero error on failure. 125 */ 126int | 105 u_int32_t rp_xid; /* request transaction id */ 106 int32_t rp_direction; /* call direction (1) */ 107 int32_t rp_astatus; /* accept status (0: accepted) */ 108 union { 109 u_int32_t rpu_errno; 110 struct { 111 struct auth_info rok_auth; 112 u_int32_t rok_status; --- 14 unchanged lines hidden (view full) --- 127 */ 128#define MAX_RESEND_DELAY 5 /* seconds */ 129 130/* 131 * Call portmap to lookup a port number for a particular rpc program 132 * Returns non-zero error on failure. 133 */ 134int |
127krpc_portmap(sin, prog, vers, portp, td) 128 struct sockaddr_in *sin; /* server address */ 129 u_int prog, vers; /* host order */ 130 u_int16_t *portp; /* network order */ 131 struct thread *td; | 135krpc_portmap(struct sockaddr_in *sin, u_int prog, u_int vers, u_int16_t *portp, 136 struct thread *td) |
132{ 133 struct sdata { 134 u_int32_t prog; /* call program */ 135 u_int32_t vers; /* call version */ 136 u_int32_t proto; /* call protocol */ 137 u_int32_t port; /* call port (unused) */ 138 } *sdata; 139 struct rdata { --- 4 unchanged lines hidden (view full) --- 144 int error; 145 146 /* The portmapper port is fixed. */ 147 if (prog == PMAPPROG) { 148 *portp = htons(PMAPPORT); 149 return 0; 150 } 151 | 137{ 138 struct sdata { 139 u_int32_t prog; /* call program */ 140 u_int32_t vers; /* call version */ 141 u_int32_t proto; /* call protocol */ 142 u_int32_t port; /* call port (unused) */ 143 } *sdata; 144 struct rdata { --- 4 unchanged lines hidden (view full) --- 149 int error; 150 151 /* The portmapper port is fixed. */ 152 if (prog == PMAPPROG) { 153 *portp = htons(PMAPPORT); 154 return 0; 155 } 156 |
152 m = m_get(M_TRYWAIT, MT_DATA); 153 if (m == NULL) 154 return ENOBUFS; | 157 m = m_get(M_WAIT, MT_DATA); |
155 sdata = mtod(m, struct sdata *); 156 m->m_len = sizeof(*sdata); 157 158 /* Do the RPC to get it. */ 159 sdata->prog = txdr_unsigned(prog); 160 sdata->vers = txdr_unsigned(vers); 161 sdata->proto = txdr_unsigned(IPPROTO_UDP); 162 sdata->port = 0; 163 164 sin->sin_port = htons(PMAPPORT); 165 error = krpc_call(sin, PMAPPROG, PMAPVERS, 166 PMAPPROC_GETPORT, &m, NULL, td); | 158 sdata = mtod(m, struct sdata *); 159 m->m_len = sizeof(*sdata); 160 161 /* Do the RPC to get it. */ 162 sdata->prog = txdr_unsigned(prog); 163 sdata->vers = txdr_unsigned(vers); 164 sdata->proto = txdr_unsigned(IPPROTO_UDP); 165 sdata->port = 0; 166 167 sin->sin_port = htons(PMAPPORT); 168 error = krpc_call(sin, PMAPPROG, PMAPVERS, 169 PMAPPROC_GETPORT, &m, NULL, td); |
167 if (error) | 170 if (error) |
168 return error; 169 170 if (m->m_len < sizeof(*rdata)) { 171 m = m_pullup(m, sizeof(*rdata)); 172 if (m == NULL) 173 return ENOBUFS; 174 } 175 rdata = mtod(m, struct rdata *); --- 4 unchanged lines hidden (view full) --- 180} 181 182/* 183 * Do a remote procedure call (RPC) and wait for its reply. 184 * If from_p is non-null, then we are doing broadcast, and 185 * the address from whence the response came is saved there. 186 */ 187int | 171 return error; 172 173 if (m->m_len < sizeof(*rdata)) { 174 m = m_pullup(m, sizeof(*rdata)); 175 if (m == NULL) 176 return ENOBUFS; 177 } 178 rdata = mtod(m, struct rdata *); --- 4 unchanged lines hidden (view full) --- 183} 184 185/* 186 * Do a remote procedure call (RPC) and wait for its reply. 187 * If from_p is non-null, then we are doing broadcast, and 188 * the address from whence the response came is saved there. 189 */ 190int |
188krpc_call(sa, prog, vers, func, data, from_p, td) 189 struct sockaddr_in *sa; 190 u_int prog, vers, func; 191 struct mbuf **data; /* input/output */ 192 struct sockaddr **from_p; /* output */ 193 struct thread *td; | 191krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func, 192 struct mbuf **data, struct sockaddr **from_p, struct thread *td) |
194{ 195 struct socket *so; 196 struct sockaddr_in *sin, ssin; 197 struct sockaddr *from; 198 struct mbuf *m, *nam, *mhead; | 193{ 194 struct socket *so; 195 struct sockaddr_in *sin, ssin; 196 struct sockaddr *from; 197 struct mbuf *m, *nam, *mhead; |
199 struct rpc_call *call; 200 struct rpc_reply *reply; | 198 struct krpc_call *call; 199 struct krpc_reply *reply; |
201 struct sockopt sopt; 202 struct timeval tv; 203 struct uio auio; 204 int error, rcvflg, timo, secs, len; 205 static u_int32_t xid = ~0xFF; 206 u_int16_t tport; 207 u_int32_t saddr; 208 --- 6 unchanged lines hidden (view full) --- 215 216 /* Free at end if not null. */ 217 nam = mhead = NULL; 218 from = NULL; 219 220 /* 221 * Create socket and set its recieve timeout. 222 */ | 200 struct sockopt sopt; 201 struct timeval tv; 202 struct uio auio; 203 int error, rcvflg, timo, secs, len; 204 static u_int32_t xid = ~0xFF; 205 u_int16_t tport; 206 u_int32_t saddr; 207 --- 6 unchanged lines hidden (view full) --- 214 215 /* Free at end if not null. */ 216 nam = mhead = NULL; 217 from = NULL; 218 219 /* 220 * Create socket and set its recieve timeout. 221 */ |
223 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td))) | 222 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td))) |
224 goto out; 225 226 tv.tv_sec = 1; 227 tv.tv_usec = 0; 228 bzero(&sopt, sizeof sopt); | 223 goto out; 224 225 tv.tv_sec = 1; 226 tv.tv_usec = 0; 227 bzero(&sopt, sizeof sopt); |
228 sopt.sopt_dir = SOPT_SET; |
|
229 sopt.sopt_level = SOL_SOCKET; 230 sopt.sopt_name = SO_RCVTIMEO; 231 sopt.sopt_val = &tv; 232 sopt.sopt_valsize = sizeof tv; 233 234 if ((error = sosetopt(so, &sopt)) != 0) 235 goto out; 236 --- 33 unchanged lines hidden (view full) --- 270 271 /* 272 * Setup socket address for the server. 273 */ 274 275 /* 276 * Prepend RPC message header. 277 */ | 229 sopt.sopt_level = SOL_SOCKET; 230 sopt.sopt_name = SO_RCVTIMEO; 231 sopt.sopt_val = &tv; 232 sopt.sopt_valsize = sizeof tv; 233 234 if ((error = sosetopt(so, &sopt)) != 0) 235 goto out; 236 --- 33 unchanged lines hidden (view full) --- 270 271 /* 272 * Setup socket address for the server. 273 */ 274 275 /* 276 * Prepend RPC message header. 277 */ |
278 mhead = m_gethdr(M_TRYWAIT, MT_DATA); | 278 mhead = m_gethdr(M_WAIT, MT_DATA); |
279 mhead->m_next = *data; | 279 mhead->m_next = *data; |
280 call = mtod(mhead, struct rpc_call *); | 280 call = mtod(mhead, struct krpc_call *); |
281 mhead->m_len = sizeof(*call); 282 bzero((caddr_t)call, sizeof(*call)); 283 /* rpc_call part */ 284 xid++; 285 call->rp_xid = txdr_unsigned(xid); 286 /* call->rp_direction = 0; */ 287 call->rp_rpcvers = txdr_unsigned(2); 288 call->rp_prog = txdr_unsigned(prog); 289 call->rp_vers = txdr_unsigned(vers); 290 call->rp_proc = txdr_unsigned(func); 291 /* rpc_auth part (auth_unix as root) */ | 281 mhead->m_len = sizeof(*call); 282 bzero((caddr_t)call, sizeof(*call)); 283 /* rpc_call part */ 284 xid++; 285 call->rp_xid = txdr_unsigned(xid); 286 /* call->rp_direction = 0; */ 287 call->rp_rpcvers = txdr_unsigned(2); 288 call->rp_prog = txdr_unsigned(prog); 289 call->rp_vers = txdr_unsigned(vers); 290 call->rp_proc = txdr_unsigned(func); 291 /* rpc_auth part (auth_unix as root) */ |
292 call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX); | 292 call->rpc_auth.authtype = txdr_unsigned(AUTH_UNIX); |
293 call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix)); 294 /* rpc_verf part (auth_null) */ 295 call->rpc_verf.authtype = 0; 296 call->rpc_verf.authlen = 0; 297 298 /* 299 * Setup packet header 300 */ | 293 call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix)); 294 /* rpc_verf part (auth_null) */ 295 call->rpc_verf.authtype = 0; 296 call->rpc_verf.authlen = 0; 297 298 /* 299 * Setup packet header 300 */ |
301 len = 0; 302 m = mhead; 303 while (m) { 304 len += m->m_len; 305 m = m->m_next; 306 } 307 mhead->m_pkthdr.len = len; | 301 m_fixhdr(mhead); |
308 mhead->m_pkthdr.rcvif = NULL; 309 310 /* 311 * Send it, repeatedly, until a reply is received, 312 * but delay each re-send by an increasing amount. 313 * If the delay hits the maximum, start complaining. 314 */ 315 timo = 0; 316 for (;;) { 317 /* Send RPC request (or re-send). */ | 302 mhead->m_pkthdr.rcvif = NULL; 303 304 /* 305 * Send it, repeatedly, until a reply is received, 306 * but delay each re-send by an increasing amount. 307 * If the delay hits the maximum, start complaining. 308 */ 309 timo = 0; 310 for (;;) { 311 /* Send RPC request (or re-send). */ |
318 m = m_copym(mhead, 0, M_COPYALL, M_TRYWAIT); 319 if (m == NULL) { 320 error = ENOBUFS; 321 goto out; 322 } | 312 m = m_copym(mhead, 0, M_COPYALL, M_WAIT); |
323 error = sosend(so, (struct sockaddr *)sa, NULL, m, 324 NULL, 0, td); 325 if (error) { 326 printf("krpc_call: sosend: %d\n", error); 327 goto out; 328 } 329 m = NULL; 330 --- 11 unchanged lines hidden (view full) --- 342 343 /* 344 * Wait for up to timo seconds for a reply. 345 * The socket receive timeout was set to 1 second. 346 */ 347 secs = timo; 348 while (secs > 0) { 349 if (from) { | 313 error = sosend(so, (struct sockaddr *)sa, NULL, m, 314 NULL, 0, td); 315 if (error) { 316 printf("krpc_call: sosend: %d\n", error); 317 goto out; 318 } 319 m = NULL; 320 --- 11 unchanged lines hidden (view full) --- 332 333 /* 334 * Wait for up to timo seconds for a reply. 335 * The socket receive timeout was set to 1 second. 336 */ 337 secs = timo; 338 while (secs > 0) { 339 if (from) { |
350 FREE(from, M_SONAME); | 340 free(from, M_SONAME); |
351 from = NULL; 352 } 353 if (m) { 354 m_freem(m); 355 m = NULL; 356 } | 341 from = NULL; 342 } 343 if (m) { 344 m_freem(m); 345 m = NULL; 346 } |
357 bzero(&auio,sizeof(auio)); | 347 bzero(&auio, sizeof(auio)); |
358 auio.uio_resid = len = 1<<16; 359 rcvflg = 0; 360 error = soreceive(so, &from, &auio, &m, NULL, &rcvflg); 361 if (error == EWOULDBLOCK) { 362 secs--; 363 continue; 364 } 365 if (error) 366 goto out; 367 len -= auio.uio_resid; 368 369 /* Does the reply contain at least a header? */ 370 if (len < MIN_REPLY_HDR) 371 continue; 372 if (m->m_len < MIN_REPLY_HDR) 373 continue; | 348 auio.uio_resid = len = 1<<16; 349 rcvflg = 0; 350 error = soreceive(so, &from, &auio, &m, NULL, &rcvflg); 351 if (error == EWOULDBLOCK) { 352 secs--; 353 continue; 354 } 355 if (error) 356 goto out; 357 len -= auio.uio_resid; 358 359 /* Does the reply contain at least a header? */ 360 if (len < MIN_REPLY_HDR) 361 continue; 362 if (m->m_len < MIN_REPLY_HDR) 363 continue; |
374 reply = mtod(m, struct rpc_reply *); | 364 reply = mtod(m, struct krpc_reply *); |
375 376 /* Is it the right reply? */ | 365 366 /* Is it the right reply? */ |
377 if (reply->rp_direction != txdr_unsigned(RPC_REPLY)) | 367 if (reply->rp_direction != txdr_unsigned(REPLY)) |
378 continue; 379 380 if (reply->rp_xid != txdr_unsigned(xid)) 381 continue; 382 383 /* Was RPC accepted? (authorization OK) */ 384 if (reply->rp_astatus != 0) { 385 error = fxdr_unsigned(u_int32_t, reply->rp_errno); 386 printf("rpc denied, error=%d\n", error); 387 continue; 388 } 389 390 /* Did the call succeed? */ 391 if (reply->rp_status != 0) { 392 error = fxdr_unsigned(u_int32_t, reply->rp_status); | 368 continue; 369 370 if (reply->rp_xid != txdr_unsigned(xid)) 371 continue; 372 373 /* Was RPC accepted? (authorization OK) */ 374 if (reply->rp_astatus != 0) { 375 error = fxdr_unsigned(u_int32_t, reply->rp_errno); 376 printf("rpc denied, error=%d\n", error); 377 continue; 378 } 379 380 /* Did the call succeed? */ 381 if (reply->rp_status != 0) { 382 error = fxdr_unsigned(u_int32_t, reply->rp_status); |
393 if (error == RPC_PROGMISMATCH) { | 383 if (error == PROG_MISMATCH) { |
394 error = EBADRPC; 395 goto out; 396 } 397 printf("rpc denied, status=%d\n", error); 398 continue; 399 } 400 401 goto gotreply; /* break two levels */ --- 13 unchanged lines hidden (view full) --- 415 len = sizeof(*reply); 416 if (m->m_len < len) { 417 m = m_pullup(m, len); 418 if (m == NULL) { 419 error = ENOBUFS; 420 goto out; 421 } 422 } | 384 error = EBADRPC; 385 goto out; 386 } 387 printf("rpc denied, status=%d\n", error); 388 continue; 389 } 390 391 goto gotreply; /* break two levels */ --- 13 unchanged lines hidden (view full) --- 405 len = sizeof(*reply); 406 if (m->m_len < len) { 407 m = m_pullup(m, len); 408 if (m == NULL) { 409 error = ENOBUFS; 410 goto out; 411 } 412 } |
423 reply = mtod(m, struct rpc_reply *); | 413 reply = mtod(m, struct krpc_reply *); |
424 if (reply->rp_auth.authtype != 0) { 425 len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen); 426 len = (len + 3) & ~3; /* XXX? */ 427 } 428 m_adj(m, len); 429 430 /* result */ 431 *data = m; --- 19 unchanged lines hidden (view full) --- 451 */ 452struct xdr_string { 453 u_int32_t len; /* length without null or padding */ 454 char data[4]; /* data (longer, of course) */ 455 /* data is padded to a long-word boundary */ 456}; 457 458struct mbuf * | 414 if (reply->rp_auth.authtype != 0) { 415 len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen); 416 len = (len + 3) & ~3; /* XXX? */ 417 } 418 m_adj(m, len); 419 420 /* result */ 421 *data = m; --- 19 unchanged lines hidden (view full) --- 441 */ 442struct xdr_string { 443 u_int32_t len; /* length without null or padding */ 444 char data[4]; /* data (longer, of course) */ 445 /* data is padded to a long-word boundary */ 446}; 447 448struct mbuf * |
459xdr_string_encode(str, len) 460 char *str; 461 int len; | 449xdr_string_encode(char *str, int len) |
462{ 463 struct mbuf *m; 464 struct xdr_string *xs; 465 int dlen; /* padded string length */ 466 int mlen; /* message length */ 467 468 dlen = (len + 3) & ~3; 469 mlen = dlen + 4; 470 471 if (mlen > MCLBYTES) /* If too big, we just can't do it. */ 472 return (NULL); 473 | 450{ 451 struct mbuf *m; 452 struct xdr_string *xs; 453 int dlen; /* padded string length */ 454 int mlen; /* message length */ 455 456 dlen = (len + 3) & ~3; 457 mlen = dlen + 4; 458 459 if (mlen > MCLBYTES) /* If too big, we just can't do it. */ 460 return (NULL); 461 |
474 m = m_get(M_TRYWAIT, MT_DATA); 475 if (mlen > MLEN) { 476 MCLGET(m, M_TRYWAIT); 477 if ((m->m_flags & M_EXT) == 0) { 478 (void) m_free(m); /* There can be only one. */ 479 return (NULL); 480 } 481 } | 462 m = m_get(M_WAIT, MT_DATA); 463 if (mlen > MLEN) 464 MCLGET(m, M_WAIT); |
482 xs = mtod(m, struct xdr_string *); 483 m->m_len = mlen; 484 xs->len = txdr_unsigned(len); 485 bcopy(str, xs->data, len); 486 return (m); 487} | 465 xs = mtod(m, struct xdr_string *); 466 m->m_len = mlen; 467 xs->len = txdr_unsigned(len); 468 bcopy(str, xs->data, len); 469 return (m); 470} |