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