Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / setkey / test-pfkey.c
blobb5c8786546b048f85a907fb87c96629b5a1cb12f
1 /* $NetBSD: test-pfkey.c,v 1.6 2006/09/09 16:22:37 manu Exp $ */
3 /* $KAME: test-pfkey.c,v 1.4 2000/06/07 00:29:14 itojun Exp $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <net/route.h>
38 #include <net/pfkeyv2.h>
39 #include <netinet/in.h>
40 #include <netkey/keydb.h>
41 #include <netkey/key_var.h>
42 #include <netkey/key_debug.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <limits.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <unistd.h>
50 #include <errno.h>
51 #include <netdb.h>
53 u_char m_buf[BUFSIZ];
54 u_int m_len;
55 char *pname;
57 void Usage __P((void));
58 int sendkeymsg __P((void));
59 void key_setsadbmsg __P((u_int));
60 void key_setsadbsens __P((void));
61 void key_setsadbprop __P((void));
62 void key_setsadbid __P((u_int, caddr_t));
63 void key_setsadblft __P((u_int, u_int));
64 void key_setspirange __P((void));
65 void key_setsadbkey __P((u_int, caddr_t));
66 void key_setsadbsa __P((void));
67 void key_setsadbaddr __P((u_int, u_int, caddr_t));
68 void key_setsadbextbuf __P((caddr_t, int, caddr_t, int, caddr_t, int));
70 void
71 Usage()
73 printf("Usage:\t%s number\n", pname);
74 exit(0);
77 int
78 main(ac, av)
79 int ac;
80 char **av;
82 pname = *av;
84 if (ac == 1) Usage();
86 key_setsadbmsg(atoi(*(av+1)));
87 sendkeymsg();
89 exit(0);
92 /* %%% */
93 int
94 sendkeymsg()
96 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
97 int so, len;
99 if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
100 perror("socket(PF_KEY)");
101 goto end;
103 #if 0
105 #include <sys/time.h>
106 struct timeval tv;
107 tv.tv_sec = 1;
108 tv.tv_usec = 0;
109 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
110 perror("setsockopt");
111 goto end;
114 #endif
116 pfkey_sadump((struct sadb_msg *)m_buf);
118 if ((len = send(so, m_buf, m_len, 0)) < 0) {
119 perror("send");
120 goto end;
123 if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
124 perror("recv");
125 goto end;
128 pfkey_sadump((struct sadb_msg *)rbuf);
130 end:
131 (void)close(so);
132 return(0);
135 void
136 key_setsadbmsg(type)
137 u_int type;
139 struct sadb_msg m_msg;
141 memset(&m_msg, 0, sizeof(m_msg));
142 m_msg.sadb_msg_version = PF_KEY_V2;
143 m_msg.sadb_msg_type = type;
144 m_msg.sadb_msg_errno = 0;
145 m_msg.sadb_msg_satype = SADB_SATYPE_ESP;
146 #if 0
147 m_msg.sadb_msg_reserved = 0;
148 #endif
149 m_msg.sadb_msg_seq = 0;
150 m_msg.sadb_msg_pid = getpid();
152 m_len = sizeof(struct sadb_msg);
153 memcpy(m_buf, &m_msg, m_len);
155 switch (type) {
156 case SADB_GETSPI:
157 /*<base, address(SD), SPI range>*/
158 key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "10.0.3.4");
159 key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "127.0.0.1");
160 key_setspirange();
161 /*<base, SA(*), address(SD)>*/
162 break;
164 case SADB_ADD:
165 /* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
166 key(AE), (identity(SD),) (sensitivity)> */
167 key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
168 case SADB_UPDATE:
169 key_setsadbsa();
170 key_setsadblft(SADB_EXT_LIFETIME_HARD, 10);
171 key_setsadblft(SADB_EXT_LIFETIME_SOFT, 5);
172 key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
173 key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
174 /* XXX key_setsadbkey(SADB_EXT_KEY_AUTH, "abcde"); */
175 key_setsadbkey(SADB_EXT_KEY_AUTH, "1234567812345678");
176 key_setsadbkey(SADB_EXT_KEY_ENCRYPT, "12345678");
177 key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com");
178 key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net");
179 key_setsadbsens();
180 /* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
181 (identity(SD),) (sensitivity)> */
182 break;
184 case SADB_DELETE:
185 /* <base, SA(*), address(SDP)> */
186 key_setsadbsa();
187 key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
188 key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
189 key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
190 /* <base, SA(*), address(SDP)> */
191 break;
193 case SADB_GET:
194 /* <base, SA(*), address(SDP)> */
195 key_setsadbsa();
196 key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
197 key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
198 key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
199 /* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
200 key(AE), (identity(SD),) (sensitivity)> */
201 break;
203 case SADB_ACQUIRE:
204 /* <base, address(SD), (address(P),) (identity(SD),)
205 (sensitivity,) proposal> */
206 key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
207 key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
208 key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
209 key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com");
210 key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net");
211 key_setsadbsens();
212 key_setsadbprop();
213 /* <base, address(SD), (address(P),) (identity(SD),)
214 (sensitivity,) proposal> */
215 break;
217 case SADB_REGISTER:
218 /* <base> */
219 /* <base, supported> */
220 break;
222 case SADB_EXPIRE:
223 case SADB_FLUSH:
224 break;
226 case SADB_DUMP:
227 break;
229 case SADB_X_PROMISC:
230 /* <base> */
231 /* <base, base(, others)> */
232 break;
234 case SADB_X_PCHANGE:
235 break;
237 /* for SPD management */
238 case SADB_X_SPDFLUSH:
239 case SADB_X_SPDDUMP:
240 break;
242 case SADB_X_SPDADD:
243 #if 0
245 struct sadb_x_policy m_policy;
247 m_policy.sadb_x_policy_len = PFKEY_UNIT64(sizeof(m_policy));
248 m_policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
249 m_policy.sadb_x_policy_type = SADB_X_PL_IPSEC;
250 m_policy.sadb_x_policy_esp_trans = 1;
251 m_policy.sadb_x_policy_ah_trans = 2;
252 m_policy.sadb_x_policy_esp_network = 3;
253 m_policy.sadb_x_policy_ah_network = 4;
254 m_policy.sadb_x_policy_reserved = 0;
256 memcpy(m_buf + m_len, &m_policy, sizeof(struct sadb_x_policy));
257 m_len += sizeof(struct sadb_x_policy);
259 #endif
261 case SADB_X_SPDDELETE:
262 key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
263 key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
264 break;
267 ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
269 return;
272 void
273 key_setsadbsens()
275 struct sadb_sens m_sens;
276 u_char buf[64];
277 u_int s, i, slen, ilen, len;
279 /* make sens & integ */
280 s = htonl(0x01234567);
281 i = htonl(0x89abcdef);
282 slen = sizeof(s);
283 ilen = sizeof(i);
284 memcpy(buf, &s, slen);
285 memcpy(buf + slen, &i, ilen);
287 len = sizeof(m_sens) + PFKEY_ALIGN8(slen) + PFKEY_ALIGN8(ilen);
288 m_sens.sadb_sens_len = PFKEY_UNIT64(len);
289 m_sens.sadb_sens_exttype = SADB_EXT_SENSITIVITY;
290 m_sens.sadb_sens_dpd = 1;
291 m_sens.sadb_sens_sens_level = 2;
292 m_sens.sadb_sens_sens_len = PFKEY_ALIGN8(slen);
293 m_sens.sadb_sens_integ_level = 3;
294 m_sens.sadb_sens_integ_len = PFKEY_ALIGN8(ilen);
295 m_sens.sadb_sens_reserved = 0;
297 key_setsadbextbuf(m_buf, m_len,
298 (caddr_t)&m_sens, sizeof(struct sadb_sens),
299 buf, slen + ilen);
300 m_len += len;
302 return;
305 void
306 key_setsadbprop()
308 struct sadb_prop m_prop;
309 struct sadb_comb *m_comb;
310 u_char buf[256];
311 #if (defined(SADB_X_EALG_AESCBC) || defined(SADB_X_EALG_CAMELLIACBC)) && defined(SADB_X_AALG_SHA2_256)
312 u_int len = sizeof(m_prop) + sizeof(m_comb) * 3;
313 #else
314 u_int len = sizeof(m_prop) + sizeof(m_comb) * 2;
315 #endif
317 /* make prop & comb */
318 m_prop.sadb_prop_len = PFKEY_UNIT64(len);
319 m_prop.sadb_prop_exttype = SADB_EXT_PROPOSAL;
320 m_prop.sadb_prop_replay = 0;
321 m_prop.sadb_prop_reserved[0] = 0;
322 m_prop.sadb_prop_reserved[1] = 0;
323 m_prop.sadb_prop_reserved[2] = 0;
325 /* the 1st is ESP DES-CBC HMAC-MD5 */
326 m_comb = (struct sadb_comb *)buf;
327 m_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
328 m_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
329 m_comb->sadb_comb_flags = 0;
330 m_comb->sadb_comb_auth_minbits = 8;
331 m_comb->sadb_comb_auth_maxbits = 96;
332 m_comb->sadb_comb_encrypt_minbits = 64;
333 m_comb->sadb_comb_encrypt_maxbits = 64;
334 m_comb->sadb_comb_reserved = 0;
335 m_comb->sadb_comb_soft_allocations = 0;
336 m_comb->sadb_comb_hard_allocations = 0;
337 m_comb->sadb_comb_soft_bytes = 0;
338 m_comb->sadb_comb_hard_bytes = 0;
339 m_comb->sadb_comb_soft_addtime = 0;
340 m_comb->sadb_comb_hard_addtime = 0;
341 m_comb->sadb_comb_soft_usetime = 0;
342 m_comb->sadb_comb_hard_usetime = 0;
344 /* the 2st is ESP 3DES-CBC and AH HMAC-SHA1 */
345 m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
346 m_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
347 m_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
348 m_comb->sadb_comb_flags = 0;
349 m_comb->sadb_comb_auth_minbits = 8;
350 m_comb->sadb_comb_auth_maxbits = 96;
351 m_comb->sadb_comb_encrypt_minbits = 64;
352 m_comb->sadb_comb_encrypt_maxbits = 64;
353 m_comb->sadb_comb_reserved = 0;
354 m_comb->sadb_comb_soft_allocations = 0;
355 m_comb->sadb_comb_hard_allocations = 0;
356 m_comb->sadb_comb_soft_bytes = 0;
357 m_comb->sadb_comb_hard_bytes = 0;
358 m_comb->sadb_comb_soft_addtime = 0;
359 m_comb->sadb_comb_hard_addtime = 0;
360 m_comb->sadb_comb_soft_usetime = 0;
361 m_comb->sadb_comb_hard_usetime = 0;
363 key_setsadbextbuf(m_buf, m_len,
364 (caddr_t)&m_prop, sizeof(struct sadb_prop),
365 buf, sizeof(*m_comb) * 2);
366 m_len += len;
368 #if defined(SADB_X_EALG_AESCBC) && defined(SADB_X_AALG_SHA2_256)
369 /* the 3rd is ESP AES-CBC and AH HMAC-SHA256 */
370 m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
371 m_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
372 m_comb->sadb_comb_encrypt = SADB_X_EALG_AESCBC;
373 m_comb->sadb_comb_flags = 0;
374 m_comb->sadb_comb_auth_minbits = 8;
375 m_comb->sadb_comb_auth_maxbits = 96;
376 m_comb->sadb_comb_encrypt_minbits = 128;
377 m_comb->sadb_comb_encrypt_maxbits = 128;
378 m_comb->sadb_comb_reserved = 0;
379 m_comb->sadb_comb_soft_allocations = 0;
380 m_comb->sadb_comb_hard_allocations = 0;
381 m_comb->sadb_comb_soft_bytes = 0;
382 m_comb->sadb_comb_hard_bytes = 0;
383 m_comb->sadb_comb_soft_addtime = 0;
384 m_comb->sadb_comb_hard_addtime = 0;
385 m_comb->sadb_comb_soft_usetime = 0;
386 m_comb->sadb_comb_hard_usetime = 0;
388 key_setsadbextbuf(m_buf, m_len,
389 (caddr_t)&m_prop, sizeof(struct sadb_prop),
390 buf, sizeof(*m_comb) * 3);
391 m_len += len;
392 #elif defined(SADB_X_EALG_CAMELLIACBC) && defined(SADB_X_AALG_SHA2_256)
393 /* the 3rd is ESP CAMELLIA-CBC and AH HMAC-SHA256 */
394 m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
395 m_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
396 m_comb->sadb_comb_encrypt = SADB_X_EALG_CAMELLIACBC;
397 m_comb->sadb_comb_flags = 0;
398 m_comb->sadb_comb_auth_minbits = 8;
399 m_comb->sadb_comb_auth_maxbits = 96;
400 m_comb->sadb_comb_encrypt_minbits = 128;
401 m_comb->sadb_comb_encrypt_maxbits = 128;
402 m_comb->sadb_comb_reserved = 0;
403 m_comb->sadb_comb_soft_allocations = 0;
404 m_comb->sadb_comb_hard_allocations = 0;
405 m_comb->sadb_comb_soft_bytes = 0;
406 m_comb->sadb_comb_hard_bytes = 0;
407 m_comb->sadb_comb_soft_addtime = 0;
408 m_comb->sadb_comb_hard_addtime = 0;
409 m_comb->sadb_comb_soft_usetime = 0;
410 m_comb->sadb_comb_hard_usetime = 0;
412 key_setsadbextbuf(m_buf, m_len,
413 (caddr_t)&m_prop, sizeof(struct sadb_prop),
414 buf, sizeof(*m_comb) * 3);
415 m_len += len;
416 #else
417 key_setsadbextbuf(m_buf, m_len,
418 (caddr_t)&m_prop, sizeof(struct sadb_prop),
419 buf, sizeof(*m_comb) * 2);
420 m_len += len;
421 #endif
422 return;
425 void
426 key_setsadbid(ext, str)
427 u_int ext;
428 caddr_t str;
430 struct sadb_ident m_id;
431 u_int idlen = strlen(str), len;
433 len = sizeof(m_id) + PFKEY_ALIGN8(idlen);
434 m_id.sadb_ident_len = PFKEY_UNIT64(len);
435 m_id.sadb_ident_exttype = ext;
436 m_id.sadb_ident_type = SADB_IDENTTYPE_USERFQDN;
437 m_id.sadb_ident_reserved = 0;
438 m_id.sadb_ident_id = getpid();
440 key_setsadbextbuf(m_buf, m_len,
441 (caddr_t)&m_id, sizeof(struct sadb_ident),
442 str, idlen);
443 m_len += len;
445 return;
448 void
449 key_setsadblft(ext, time)
450 u_int ext, time;
452 struct sadb_lifetime m_lft;
454 m_lft.sadb_lifetime_len = PFKEY_UNIT64(sizeof(m_lft));
455 m_lft.sadb_lifetime_exttype = ext;
456 m_lft.sadb_lifetime_allocations = 0x2;
457 m_lft.sadb_lifetime_bytes = 0x1000;
458 m_lft.sadb_lifetime_addtime = time;
459 m_lft.sadb_lifetime_usetime = 0x0020;
461 memcpy(m_buf + m_len, &m_lft, sizeof(struct sadb_lifetime));
462 m_len += sizeof(struct sadb_lifetime);
464 return;
467 void
468 key_setspirange()
470 struct sadb_spirange m_spi;
472 m_spi.sadb_spirange_len = PFKEY_UNIT64(sizeof(m_spi));
473 m_spi.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
474 m_spi.sadb_spirange_min = 0x00001000;
475 m_spi.sadb_spirange_max = 0x00002000;
476 m_spi.sadb_spirange_reserved = 0;
478 memcpy(m_buf + m_len, &m_spi, sizeof(struct sadb_spirange));
479 m_len += sizeof(struct sadb_spirange);
481 return;
484 void
485 key_setsadbkey(ext, str)
486 u_int ext;
487 caddr_t str;
489 struct sadb_key m_key;
490 u_int keylen = strlen(str);
491 u_int len;
493 len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
494 m_key.sadb_key_len = PFKEY_UNIT64(len);
495 m_key.sadb_key_exttype = ext;
496 m_key.sadb_key_bits = keylen * 8;
497 m_key.sadb_key_reserved = 0;
499 key_setsadbextbuf(m_buf, m_len,
500 (caddr_t)&m_key, sizeof(struct sadb_key),
501 str, keylen);
502 m_len += len;
504 return;
507 void
508 key_setsadbsa()
510 struct sadb_sa m_sa;
512 m_sa.sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa));
513 m_sa.sadb_sa_exttype = SADB_EXT_SA;
514 m_sa.sadb_sa_spi = htonl(0x12345678);
515 m_sa.sadb_sa_replay = 4;
516 m_sa.sadb_sa_state = 0;
517 m_sa.sadb_sa_auth = SADB_AALG_MD5HMAC;
518 m_sa.sadb_sa_encrypt = SADB_EALG_DESCBC;
519 m_sa.sadb_sa_flags = 0;
521 memcpy(m_buf + m_len, &m_sa, sizeof(struct sadb_sa));
522 m_len += sizeof(struct sadb_sa);
524 return;
527 void
528 key_setsadbaddr(ext, af, str)
529 u_int ext, af;
530 caddr_t str;
532 struct sadb_address m_addr;
533 u_int len;
534 struct addrinfo hints, *res;
535 const char *serv;
536 int plen;
538 switch (af) {
539 case AF_INET:
540 plen = sizeof(struct in_addr) << 3;
541 break;
542 case AF_INET6:
543 plen = sizeof(struct in6_addr) << 3;
544 break;
545 default:
546 /* XXX bark */
547 exit(1);
550 /* make sockaddr buffer */
551 memset(&hints, 0, sizeof(hints));
552 hints.ai_family = af;
553 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
554 hints.ai_flags = AI_NUMERICHOST;
555 serv = (ext == SADB_EXT_ADDRESS_PROXY ? "0" : "4660"); /*0x1234*/
556 if (getaddrinfo(str, serv, &hints, &res) != 0 || res->ai_next) {
557 /* XXX bark */
558 exit(1);
561 len = sizeof(struct sadb_address) + PFKEY_ALIGN8(res->ai_addrlen);
562 m_addr.sadb_address_len = PFKEY_UNIT64(len);
563 m_addr.sadb_address_exttype = ext;
564 m_addr.sadb_address_proto =
565 (ext == SADB_EXT_ADDRESS_PROXY ? 0 : IPPROTO_TCP);
566 m_addr.sadb_address_prefixlen = plen;
567 m_addr.sadb_address_reserved = 0;
569 key_setsadbextbuf(m_buf, m_len,
570 (caddr_t)&m_addr, sizeof(struct sadb_address),
571 (caddr_t)res->ai_addr, res->ai_addrlen);
572 m_len += len;
574 freeaddrinfo(res);
576 return;
579 void
580 key_setsadbextbuf(dst, off, ebuf, elen, vbuf, vlen)
581 caddr_t dst, ebuf, vbuf;
582 int off, elen, vlen;
584 memset(dst + off, 0, elen + vlen);
585 memcpy(dst + off, (caddr_t)ebuf, elen);
586 memcpy(dst + off + elen, vbuf, vlen);
588 return;