1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 #include <sunrpc.h> 5 6 /* 7 * RPC protocol constants 8 */ 9 enum 10 { 11 RpcVersion = 2, 12 13 /* msg type */ 14 MsgCall = 0, 15 MsgReply = 1, 16 17 /* reply stat */ 18 MsgAccepted = 0, 19 MsgDenied = 1, 20 21 /* accept stat */ 22 MsgSuccess = 0, 23 MsgProgUnavail = 1, 24 MsgProgMismatch = 2, 25 MsgProcUnavail = 3, 26 MsgGarbageArgs = 4, 27 MsgSystemErr = 5, 28 29 /* reject stat */ 30 MsgRpcMismatch = 0, 31 MsgAuthError = 1, 32 33 /* msg auth xxx */ 34 MsgAuthOk = 0, 35 MsgAuthBadCred = 1, 36 MsgAuthRejectedCred = 2, 37 MsgAuthBadVerf = 3, 38 MsgAuthRejectedVerf = 4, 39 MsgAuthTooWeak = 5, 40 MsgAuthInvalidResp = 6, 41 MsgAuthFailed = 7, 42 }; 43 44 SunStatus 45 sunRpcPack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc) 46 { 47 u32int x; 48 49 if(sunUint32Pack(a, ea, &a, &rpc->xid) < 0) 50 goto Err; 51 if(rpc->iscall){ 52 if(sunUint32Pack(a, ea, &a, (x=MsgCall, &x)) < 0 53 || sunUint32Pack(a, ea, &a, (x=RpcVersion, &x)) < 0 54 || sunUint32Pack(a, ea, &a, &rpc->prog) < 0 55 || sunUint32Pack(a, ea, &a, &rpc->vers) < 0 56 || sunUint32Pack(a, ea, &a, &rpc->proc) < 0 57 || sunAuthInfoPack(a, ea, &a, &rpc->cred) < 0 58 || sunAuthInfoPack(a, ea, &a, &rpc->verf) < 0 59 || sunFixedOpaquePack(a, ea, &a, rpc->data, rpc->ndata) < 0) 60 goto Err; 61 }else{ 62 if(sunUint32Pack(a, ea, &a, (x=MsgReply, &x)) < 0) 63 goto Err; 64 switch(rpc->status&0xF0000){ 65 case 0: 66 case SunAcceptError: 67 if(sunUint32Pack(a, ea, &a, (x=MsgAccepted, &x)) < 0 68 || sunAuthInfoPack(a, ea, &a, &rpc->verf) < 0) 69 goto Err; 70 break; 71 default: 72 if(sunUint32Pack(a, ea, &a, (x=MsgDenied, &x)) < 0) 73 goto Err; 74 break; 75 } 76 77 switch(rpc->status){ 78 case SunSuccess: 79 if(sunUint32Pack(a, ea, &a, (x=MsgSuccess, &x)) < 0 80 || sunFixedOpaquePack(a, ea, &a, rpc->data, rpc->ndata) < 0) 81 goto Err; 82 break; 83 case SunRpcMismatch: 84 case SunProgMismatch: 85 if(sunUint32Pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0 86 || sunUint32Pack(a, ea, &a, &rpc->low) < 0 87 || sunUint32Pack(a, ea, &a, &rpc->high) < 0) 88 goto Err; 89 break; 90 default: 91 if(sunUint32Pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0) 92 goto Err; 93 break; 94 } 95 } 96 *pa = a; 97 return SunSuccess; 98 99 Err: 100 *pa = ea; 101 return SunGarbageArgs; 102 } 103 104 uint 105 sunRpcSize(SunRpc *rpc) 106 { 107 uint a; 108 109 a = 4; 110 if(rpc->iscall){ 111 a += 5*4; 112 a += sunAuthInfoSize(&rpc->cred); 113 a += sunAuthInfoSize(&rpc->verf); 114 a += sunFixedOpaqueSize(rpc->ndata); 115 }else{ 116 a += 4; 117 switch(rpc->status&0xF0000){ 118 case 0: 119 case SunAcceptError: 120 a += 4+sunAuthInfoSize(&rpc->verf); 121 break; 122 default: 123 a += 4; 124 break; 125 } 126 127 switch(rpc->status){ 128 case SunSuccess: 129 a += 4+sunFixedOpaqueSize(rpc->ndata); 130 break; 131 case SunRpcMismatch: 132 case SunProgMismatch: 133 a += 3*4; 134 default: 135 a += 4; 136 } 137 } 138 return a; 139 } 140 141 SunStatus 142 sunRpcUnpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc) 143 { 144 u32int x; 145 146 memset(rpc, 0, sizeof *rpc); 147 if(sunUint32Unpack(a, ea, &a, &rpc->xid) < 0 148 || sunUint32Unpack(a, ea, &a, &x) < 0) 149 goto Err; 150 151 switch(x){ 152 default: 153 goto Err; 154 case MsgCall: 155 rpc->iscall = 1; 156 if(sunUint32Unpack(a, ea, &a, &x) < 0 || x != RpcVersion 157 || sunUint32Unpack(a, ea, &a, &rpc->prog) < 0 158 || sunUint32Unpack(a, ea, &a, &rpc->vers) < 0 159 || sunUint32Unpack(a, ea, &a, &rpc->proc) < 0 160 || sunAuthInfoUnpack(a, ea, &a, &rpc->cred) < 0 161 || sunAuthInfoUnpack(a, ea, &a, &rpc->verf) < 0) 162 goto Err; 163 rpc->ndata = ea-a; 164 rpc->data = a; 165 a = ea; 166 break; 167 168 case MsgReply: 169 rpc->iscall = 0; 170 if(sunUint32Unpack(a, ea, &a, &x) < 0) 171 goto Err; 172 switch(x){ 173 default: 174 goto Err; 175 case MsgAccepted: 176 if(sunAuthInfoUnpack(a, ea, &a, &rpc->verf) < 0 177 || sunUint32Unpack(a, ea, &a, &x) < 0) 178 goto Err; 179 switch(x){ 180 case MsgSuccess: 181 rpc->status = SunSuccess; 182 rpc->ndata = ea-a; 183 rpc->data = a; 184 a = ea; 185 break; 186 case MsgProgUnavail: 187 case MsgProcUnavail: 188 case MsgGarbageArgs: 189 case MsgSystemErr: 190 rpc->status = SunAcceptError | x; 191 break; 192 case MsgProgMismatch: 193 rpc->status = SunAcceptError | x; 194 if(sunUint32Unpack(a, ea, &a, &rpc->low) < 0 195 || sunUint32Unpack(a, ea, &a, &rpc->high) < 0) 196 goto Err; 197 break; 198 } 199 break; 200 case MsgDenied: 201 if(sunUint32Unpack(a, ea, &a, &x) < 0) 202 goto Err; 203 switch(x){ 204 default: 205 goto Err; 206 case MsgAuthError: 207 if(sunUint32Unpack(a, ea, &a, &x) < 0) 208 goto Err; 209 rpc->status = SunAuthError | x; 210 break; 211 case MsgRpcMismatch: 212 rpc->status = SunRejectError | x; 213 if(sunUint32Unpack(a, ea, &a, &rpc->low) < 0 214 || sunUint32Unpack(a, ea, &a, &rpc->high) < 0) 215 goto Err; 216 break; 217 } 218 break; 219 } 220 } 221 *pa = a; 222 return SunSuccess; 223 224 Err: 225 *pa = ea; 226 return SunGarbageArgs; 227 } 228 229 void 230 sunRpcPrint(Fmt *fmt, SunRpc *rpc) 231 { 232 fmtprint(fmt, "xid=%#ux", rpc->xid); 233 if(rpc->iscall){ 234 fmtprint(fmt, " prog %#ux vers %#ux proc %#ux [", rpc->prog, rpc->vers, rpc->proc); 235 sunAuthInfoPrint(fmt, &rpc->cred); 236 fmtprint(fmt, "] ["); 237 sunAuthInfoPrint(fmt, &rpc->verf); 238 fmtprint(fmt, "]"); 239 }else{ 240 fmtprint(fmt, " status %#ux [", rpc->status); 241 sunAuthInfoPrint(fmt, &rpc->verf); 242 fmtprint(fmt, "] low %#ux high %#ux", rpc->low, rpc->high); 243 } 244 } 245 246 void 247 sunAuthInfoPrint(Fmt *fmt, SunAuthInfo *ai) 248 { 249 switch(ai->flavor){ 250 case SunAuthNone: 251 fmtprint(fmt, "none"); 252 break; 253 case SunAuthShort: 254 fmtprint(fmt, "short"); 255 break; 256 case SunAuthSys: 257 fmtprint(fmt, "sys"); 258 break; 259 default: 260 fmtprint(fmt, "%#ux", ai->flavor); 261 break; 262 } 263 // if(ai->ndata) 264 // fmtprint(fmt, " %.*H", ai->ndata, ai->data); 265 } 266 267 uint 268 sunAuthInfoSize(SunAuthInfo *ai) 269 { 270 return 4 + sunVarOpaqueSize(ai->ndata); 271 } 272 273 int 274 sunAuthInfoPack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai) 275 { 276 if(sunUint32Pack(a, ea, &a, &ai->flavor) < 0 277 || sunVarOpaquePack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0) 278 goto Err; 279 *pa = a; 280 return 0; 281 282 Err: 283 *pa = ea; 284 return -1; 285 } 286 287 int 288 sunAuthInfoUnpack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai) 289 { 290 if(sunUint32Unpack(a, ea, &a, &ai->flavor) < 0 291 || sunVarOpaqueUnpack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0) 292 goto Err; 293 *pa = a; 294 return 0; 295 296 Err: 297 *pa = ea; 298 return -1; 299 } 300 301 int 302 sunEnumPack(uchar *a, uchar *ea, uchar **pa, int *e) 303 { 304 u32int x; 305 306 x = *e; 307 return sunUint32Pack(a, ea, pa, &x); 308 } 309 310 int 311 sunUint1Pack(uchar *a, uchar *ea, uchar **pa, u1int *u) 312 { 313 u32int x; 314 315 x = *u; 316 return sunUint32Pack(a, ea, pa, &x); 317 } 318 319 int 320 sunUint32Pack(uchar *a, uchar *ea, uchar **pa, u32int *u) 321 { 322 u32int x; 323 324 if(ea-a < 4) 325 goto Err; 326 327 x = *u; 328 *a++ = x>>24; 329 *a++ = x>>16; 330 *a++ = x>>8; 331 *a++ = x; 332 *pa = a; 333 return 0; 334 335 Err: 336 *pa = ea; 337 return -1; 338 } 339 340 int 341 sunEnumUnpack(uchar *a, uchar *ea, uchar **pa, int *e) 342 { 343 u32int x; 344 if(sunUint32Unpack(a, ea, pa, &x) < 0) 345 return -1; 346 *e = x; 347 return 0; 348 } 349 350 int 351 sunUint1Unpack(uchar *a, uchar *ea, uchar **pa, u1int *u) 352 { 353 u32int x; 354 if(sunUint32Unpack(a, ea, pa, &x) < 0 || (x!=0 && x!=1)){ 355 *pa = ea; 356 return -1; 357 } 358 *u = x; 359 return 0; 360 } 361 362 int 363 sunUint32Unpack(uchar *a, uchar *ea, uchar **pa, u32int *u) 364 { 365 u32int x; 366 367 if(ea-a < 4) 368 goto Err; 369 x = *a++ << 24; 370 x |= *a++ << 16; 371 x |= *a++ << 8; 372 x |= *a++; 373 *pa = a; 374 *u = x; 375 return 0; 376 377 Err: 378 *pa = ea; 379 return -1; 380 } 381 382 int 383 sunUint64Unpack(uchar *a, uchar *ea, uchar **pa, u64int *u) 384 { 385 u32int x, y; 386 387 if(sunUint32Unpack(a, ea, &a, &x) < 0 388 || sunUint32Unpack(a, ea, &a, &y) < 0) 389 goto Err; 390 *u = ((uvlong)x<<32) | y; 391 *pa = a; 392 return 0; 393 Err: 394 *pa = ea; 395 return -1; 396 } 397 398 int 399 sunUint64Pack(uchar *a, uchar *ea, uchar **pa, u64int *u) 400 { 401 u32int x, y; 402 403 x = *u >> 32; 404 y = *u; 405 if(sunUint32Pack(a, ea, &a, &x) < 0 406 || sunUint32Pack(a, ea, &a, &y) < 0) 407 goto Err; 408 *pa = a; 409 return 0; 410 Err: 411 *pa = ea; 412 return -1; 413 } 414 415 uint 416 sunStringSize(char *s) 417 { 418 return (4+strlen(s)+3) & ~3; 419 } 420 421 int 422 sunStringUnpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max) 423 { 424 uchar *dat; 425 u32int n; 426 427 if(sunVarOpaqueUnpack(a, ea, pa, &dat, &n, max) < 0) 428 goto Err; 429 /* slide string down over length to make room for NUL */ 430 memmove(dat-1, dat, n); 431 dat[-1+n] = 0; 432 *s = (char*)(dat-1); 433 return 0; 434 Err: 435 return -1; 436 } 437 438 int 439 sunStringPack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max) 440 { 441 u32int n; 442 443 n = strlen(*s); 444 return sunVarOpaquePack(a, ea, pa, (uchar**)s, &n, max); 445 } 446 447 uint 448 sunVarOpaqueSize(u32int n) 449 { 450 return (4+n+3) & ~3; 451 } 452 453 int 454 sunVarOpaquePack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max) 455 { 456 if(*ndat > max || sunUint32Pack(a, ea, &a, ndat) < 0 457 || sunFixedOpaquePack(a, ea, &a, *dat, *ndat) < 0) 458 goto Err; 459 *pa = a; 460 return 0; 461 462 Err: 463 *pa = ea; 464 return -1; 465 } 466 467 int 468 sunVarOpaqueUnpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max) 469 { 470 if(sunUint32Unpack(a, ea, &a, ndat) < 0 471 || *ndat > max) 472 goto Err; 473 *dat = a; 474 a += (*ndat+3)&~3; 475 if(a > ea) 476 goto Err; 477 *pa = a; 478 return 0; 479 480 Err: 481 *pa = ea; 482 return -1; 483 } 484 485 uint 486 sunFixedOpaqueSize(u32int n) 487 { 488 return (n+3) & ~3; 489 } 490 491 int 492 sunFixedOpaquePack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n) 493 { 494 uint nn; 495 496 nn = (n+3)&~3; 497 if(a+nn > ea) 498 goto Err; 499 memmove(a, dat, n); 500 if(nn > n) 501 memset(a+n, 0, nn-n); 502 a += nn; 503 *pa = a; 504 return 0; 505 506 Err: 507 *pa = ea; 508 return -1; 509 } 510 511 int 512 sunFixedOpaqueUnpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n) 513 { 514 uint nn; 515 516 nn = (n+3)&~3; 517 if(a+nn > ea) 518 goto Err; 519 memmove(dat, a, n); 520 a += nn; 521 *pa = a; 522 return 0; 523 524 Err: 525 *pa = ea; 526 return -1; 527 } 528 529