Annotation of embedaddon/mpd/src/l2tp_avp.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include "ppp.h"
! 42: #include "log.h"
! 43: #include "l2tp_avp.h"
! 44: #include "util.h"
! 45: #include <openssl/md5.h>
! 46:
! 47: /* Memory types */
! 48: #define AVP_MTYPE "ppp_l2tp_avp"
! 49: #define AVP_LIST_MTYPE "ppp_l2tp_avp_list"
! 50: #define AVP_PTRS_MTYPE "ppp_l2tp_avp_ptrs"
! 51:
! 52: /***********************************************************************
! 53: AVP STRUCTURE METHODS
! 54: ***********************************************************************/
! 55:
! 56: /*
! 57: * Create a new AVP structure.
! 58: */
! 59: struct ppp_l2tp_avp *
! 60: ppp_l2tp_avp_create(int mandatory, u_int16_t vendor,
! 61: u_int16_t type, const void *value, size_t vlen)
! 62: {
! 63: struct ppp_l2tp_avp *avp;
! 64:
! 65: avp = Malloc(AVP_MTYPE, sizeof(*avp));
! 66: avp->mandatory = !!mandatory;
! 67: avp->vendor = vendor;
! 68: avp->type = type;
! 69: if (vlen > 0)
! 70: avp->value = Mdup(AVP_MTYPE, value, vlen);
! 71: avp->vlen = vlen;
! 72: return (avp);
! 73: }
! 74:
! 75: /*
! 76: * Copy an AVP struture.
! 77: */
! 78: struct ppp_l2tp_avp *
! 79: ppp_l2tp_avp_copy(const struct ppp_l2tp_avp *avp)
! 80: {
! 81: return (ppp_l2tp_avp_create(avp->mandatory, avp->vendor,
! 82: avp->type, avp->value, avp->vlen));
! 83: }
! 84:
! 85: /*
! 86: * Destroy an AVP structure.
! 87: */
! 88: void
! 89: ppp_l2tp_avp_destroy(struct ppp_l2tp_avp **avpp)
! 90: {
! 91: struct ppp_l2tp_avp *const avp = *avpp;
! 92:
! 93: if (avp == NULL)
! 94: return;
! 95: *avpp = NULL;
! 96: Freee(avp->value);
! 97: Freee(avp);
! 98: }
! 99:
! 100: /***********************************************************************
! 101: AVP LIST METHODS
! 102: ***********************************************************************/
! 103:
! 104: /*
! 105: * Create a new AVP list.
! 106: */
! 107: struct ppp_l2tp_avp_list *
! 108: ppp_l2tp_avp_list_create(void)
! 109: {
! 110: return (Malloc(AVP_LIST_MTYPE, sizeof(struct ppp_l2tp_avp_list)));
! 111: }
! 112:
! 113: /*
! 114: * Insert an AVP into a list.
! 115: */
! 116: int
! 117: ppp_l2tp_avp_list_insert(struct ppp_l2tp_avp_list *list,
! 118: struct ppp_l2tp_avp **avpp, int index)
! 119: {
! 120: struct ppp_l2tp_avp *const avp = *avpp;
! 121: void *mem;
! 122:
! 123: if (avp == NULL || index < 0 || index > list->length) {
! 124: errno = EINVAL;
! 125: return (-1);
! 126: }
! 127: /* REALLOC */
! 128: mem = Malloc(AVP_LIST_MTYPE, (list->length + 1) * sizeof(*list->avps));
! 129: memcpy(mem, list->avps, list->length * sizeof(*list->avps));
! 130: Freee(list->avps);
! 131: list->avps = mem;
! 132: /* insert */
! 133: memmove(list->avps + index + 1, list->avps + index,
! 134: (list->length++ - index) * sizeof(*list->avps));
! 135: list->avps[index] = *avp;
! 136: Freee(avp);
! 137: *avpp = NULL;
! 138: return (0);
! 139: }
! 140:
! 141: /*
! 142: * Create a new AVP and add it to the end of the given list.
! 143: */
! 144: int
! 145: ppp_l2tp_avp_list_append(struct ppp_l2tp_avp_list *list, int mandatory,
! 146: u_int16_t vendor, u_int16_t type, const void *value, size_t vlen)
! 147: {
! 148: struct ppp_l2tp_avp *avp;
! 149:
! 150: avp = ppp_l2tp_avp_create(mandatory, vendor, type, value, vlen);
! 151: if (ppp_l2tp_avp_list_insert(list, &avp, list->length) == -1) {
! 152: ppp_l2tp_avp_destroy(&avp);
! 153: return (-1);
! 154: }
! 155: return (0);
! 156: }
! 157:
! 158: /*
! 159: * Extract an AVP from a list.
! 160: */
! 161: struct ppp_l2tp_avp *
! 162: ppp_l2tp_avp_list_extract(struct ppp_l2tp_avp_list *list, u_int index)
! 163: {
! 164: struct ppp_l2tp_avp *elem;
! 165: struct ppp_l2tp_avp *avp;
! 166:
! 167: if (index >= list->length) {
! 168: errno = EINVAL;
! 169: return (NULL);
! 170: }
! 171: elem = &list->avps[index];
! 172: avp = ppp_l2tp_avp_create(elem->mandatory, elem->vendor,
! 173: elem->type, elem->value, elem->vlen);
! 174: memmove(list->avps + index, list->avps + index + 1,
! 175: (--list->length - index) * sizeof(*list->avps));
! 176: return (avp);
! 177: }
! 178:
! 179: /*
! 180: * Remove and destroy an AVP from a list.
! 181: */
! 182: int
! 183: ppp_l2tp_avp_list_remove(struct ppp_l2tp_avp_list *list, u_int index)
! 184: {
! 185: if (index >= list->length) {
! 186: errno = EINVAL;
! 187: return (-1);
! 188: }
! 189: Freee(list->avps[index].value);
! 190: memmove(list->avps + index, list->avps + index + 1,
! 191: (--list->length - index) * sizeof(*list->avps));
! 192: return (0);
! 193: }
! 194:
! 195: /*
! 196: * Find an AVP in a list.
! 197: */
! 198: int
! 199: ppp_l2tp_avp_list_find(const struct ppp_l2tp_avp_list *list,
! 200: u_int16_t vendor, u_int16_t type)
! 201: {
! 202: int i;
! 203:
! 204: for (i = 0; i < list->length; i++) {
! 205: const struct ppp_l2tp_avp *const avp = &list->avps[i];
! 206:
! 207: if (avp->vendor == vendor && avp->type == type)
! 208: return (i);
! 209: }
! 210: return (-1);
! 211: }
! 212:
! 213: /*
! 214: * Copy an AVP list.
! 215: */
! 216: struct ppp_l2tp_avp_list *
! 217: ppp_l2tp_avp_list_copy(const struct ppp_l2tp_avp_list *orig)
! 218: {
! 219: struct ppp_l2tp_avp_list *list;
! 220: int i;
! 221:
! 222: list = ppp_l2tp_avp_list_create();
! 223: for (i = 0; i < orig->length; i++) {
! 224: const struct ppp_l2tp_avp *const avp = &orig->avps[i];
! 225:
! 226: if (ppp_l2tp_avp_list_append(list, avp->mandatory,
! 227: avp->vendor, avp->type, avp->value, avp->vlen) == -1) {
! 228: ppp_l2tp_avp_list_destroy(&list);
! 229: return (NULL);
! 230: }
! 231: }
! 232: return (list);
! 233: }
! 234:
! 235: /*
! 236: * Destroy an AVP list.
! 237: */
! 238: void
! 239: ppp_l2tp_avp_list_destroy(struct ppp_l2tp_avp_list **listp)
! 240: {
! 241: struct ppp_l2tp_avp_list *const list = *listp;
! 242: int i;
! 243:
! 244: if (list == NULL)
! 245: return;
! 246: *listp = NULL;
! 247: for (i = 0; i < list->length; i++) {
! 248: const struct ppp_l2tp_avp *const avp = &list->avps[i];
! 249:
! 250: Freee(avp->value);
! 251: }
! 252: Freee(list->avps);
! 253: Freee(list);
! 254: }
! 255:
! 256: /*
! 257: * Encode a list of AVP's into a single buffer, preserving the order
! 258: * of the AVP's. If a shared secret is supplied, and any of the AVP's
! 259: * are hidden, then any required random vector AVP's are created and
! 260: * inserted automatically.
! 261: */
! 262: int
! 263: ppp_l2tp_avp_pack(const struct ppp_l2tp_avp_info *info,
! 264: const struct ppp_l2tp_avp_list *list, const u_char *secret,
! 265: size_t slen, u_char *buf)
! 266: {
! 267: uint32_t randvec;
! 268: int randsent = 0;
! 269: int len;
! 270: int i;
! 271:
! 272: /* Pack AVP's */
! 273: for (len = i = 0; i < list->length; i++) {
! 274: const struct ppp_l2tp_avp *const avp = &list->avps[i];
! 275: const struct ppp_l2tp_avp_info *desc;
! 276: u_int16_t hdr[3];
! 277: int hide = 0;
! 278: int pad = 0;
! 279: int j;
! 280:
! 281: /* Find descriptor */
! 282: for (desc = info; desc->name != NULL
! 283: && (desc->vendor != avp->vendor || desc->type != avp->type);
! 284: desc++);
! 285: if (desc->name == NULL) {
! 286: errno = EILSEQ;
! 287: return (-1);
! 288: }
! 289:
! 290: /* Sanity check AVP */
! 291: if (avp->vlen < desc->min_length
! 292: || avp->vlen > desc->max_length
! 293: || avp->vlen > AVP_MAX_VLEN) {
! 294: errno = EILSEQ;
! 295: return (-1);
! 296: }
! 297:
! 298: /* Add random vector first time */
! 299: if (secret != NULL && desc->hidden_ok && randsent == 0) {
! 300: if (buf != NULL) {
! 301: memset(&hdr, 0, sizeof(hdr));
! 302: hdr[0] = AVP_MANDATORY | (sizeof(randvec) + 6);
! 303: hdr[1] = 0;
! 304: hdr[2] = AVP_RANDOM_VECTOR;
! 305: for (j = 0; j < 3; j++)
! 306: hdr[j] = htons(hdr[j]);
! 307: memcpy(buf + len, &hdr, 6);
! 308: randvec = random();
! 309: memcpy(buf + len + 6, &randvec, sizeof(randvec));
! 310: }
! 311: len += 6 + sizeof(randvec);
! 312: randsent = 1;
! 313: }
! 314:
! 315: /* Set header stuff for this AVP */
! 316: memset(&hdr, 0, sizeof(hdr));
! 317: if (avp->mandatory)
! 318: hdr[0] |= AVP_MANDATORY;
! 319: if (secret != NULL && desc->hidden_ok) {
! 320: hdr[0] |= AVP_HIDDEN;
! 321: hide = 1;
! 322: pad = 7 - (avp->vlen & 0x7);
! 323: }
! 324: hdr[0] |= (6 + (hide?2:0) + avp->vlen + pad);
! 325: hdr[1] = avp->vendor;
! 326: hdr[2] = avp->type;
! 327: for (j = 0; j < 3; j++)
! 328: hdr[j] = htons(hdr[j]);
! 329: if (buf != NULL)
! 330: memcpy(buf + len, &hdr, 6);
! 331: len += 6;
! 332:
! 333: /* Copy AVP value, optionally hiding it */
! 334: if (hide) {
! 335: if (buf != NULL) {
! 336: MD5_CTX md5ctx;
! 337: u_char hash[MD5_DIGEST_LENGTH];
! 338: int k, l;
! 339: uint16_t t;
! 340:
! 341: /* Add original length */
! 342: buf[len] = (avp->vlen >> 8);
! 343: buf[len + 1] = (avp->vlen & 0xff);
! 344:
! 345: /* Add value */
! 346: memcpy(buf + len + 2, avp->value, avp->vlen);
! 347:
! 348: /* Encrypt value */
! 349: MD5_Init(&md5ctx);
! 350: t = htons(avp->type);
! 351: MD5_Update(&md5ctx, &t, 2);
! 352: MD5_Update(&md5ctx, secret, slen);
! 353: MD5_Update(&md5ctx, &randvec, sizeof(randvec));
! 354: MD5_Final(hash, &md5ctx);
! 355: for (l = 0; l <= (2 + avp->vlen - 1)/MD5_DIGEST_LENGTH; l++) {
! 356: if (l > 0) {
! 357: MD5_Init(&md5ctx);
! 358: MD5_Update(&md5ctx, secret, slen);
! 359: MD5_Update(&md5ctx, buf + len + (l-1)*MD5_DIGEST_LENGTH, MD5_DIGEST_LENGTH);
! 360: MD5_Final(hash, &md5ctx);
! 361: }
! 362: for (k = 0;
! 363: k < MD5_DIGEST_LENGTH &&
! 364: (l*MD5_DIGEST_LENGTH+k) < (2 + avp->vlen);
! 365: k++) {
! 366: buf[len + l*MD5_DIGEST_LENGTH + k] ^=
! 367: hash[k];
! 368: }
! 369: }
! 370: }
! 371: len += 2 + avp->vlen + pad;
! 372: } else {
! 373: if (buf != NULL)
! 374: memcpy(buf + len, avp->value, avp->vlen);
! 375: len += avp->vlen;
! 376: }
! 377: }
! 378:
! 379: /* Done */
! 380: return (len);
! 381: }
! 382:
! 383: /*
! 384: * Decode a packet into an array of unpacked AVP structures, preserving
! 385: * the order of the AVP's. Random vector AVP's are automatically removed.
! 386: */
! 387: struct ppp_l2tp_avp_list *
! 388: ppp_l2tp_avp_unpack(const struct ppp_l2tp_avp_info *info,
! 389: u_char *data, size_t dlen, const u_char *secret, size_t slen)
! 390: {
! 391: struct ppp_l2tp_avp_list *list;
! 392: const u_char *randvec = NULL;
! 393: u_int16_t hdr[3];
! 394: int randvec_len = 0;
! 395: int i;
! 396:
! 397: /* Create list */
! 398: list = ppp_l2tp_avp_list_create();
! 399:
! 400: /* Unpack AVP's */
! 401: while (dlen > 0) {
! 402: const struct ppp_l2tp_avp_info *desc;
! 403: u_int16_t alen;
! 404: /* Get header */
! 405: if (dlen < 6)
! 406: goto bogus;
! 407: memcpy(&hdr, data, 6);
! 408: for (i = 0; i < 3; i++)
! 409: hdr[i] = ntohs(hdr[i]);
! 410: alen = hdr[0] & AVP_LENGTH_MASK;
! 411: if (alen < 6 || alen > dlen)
! 412: goto bogus;
! 413:
! 414: /* Check reserved bits */
! 415: if ((hdr[0] & AVP_RESERVED) != 0)
! 416: goto unknown;
! 417:
! 418: /* Find descriptor for this AVP */
! 419: for (desc = info; desc->name != NULL
! 420: && (desc->vendor != hdr[1] || desc->type != hdr[2]);
! 421: desc++);
! 422: if (desc->name == NULL) {
! 423: unknown: if ((hdr[0] & AVP_MANDATORY) != 0) {
! 424: errno = ENOSYS;
! 425: goto fail;
! 426: }
! 427: goto skip;
! 428: }
! 429:
! 430: /* Remember random vector AVP's as we see them */
! 431: if (hdr[1] == 0 && hdr[2] == AVP_RANDOM_VECTOR) {
! 432: randvec = data + 6;
! 433: randvec_len = alen - 6;
! 434: data += alen;
! 435: dlen -= alen;
! 436: continue;
! 437: }
! 438:
! 439: /* Un-hide AVP if hidden */
! 440: if ((hdr[0] & AVP_HIDDEN) != 0) {
! 441: MD5_CTX md5ctx;
! 442: u_char hash[MD5_DIGEST_LENGTH];
! 443: u_char nhash[MD5_DIGEST_LENGTH];
! 444: int k, l;
! 445: u_int16_t olen;
! 446: uint16_t t;
! 447:
! 448: if (randvec == NULL)
! 449: goto bogus;
! 450: if (secret == NULL) {
! 451: errno = EAUTH;
! 452: goto fail;
! 453: }
! 454:
! 455: /* Encrypt value */
! 456: MD5_Init(&md5ctx);
! 457: t = htons(hdr[2]);
! 458: MD5_Update(&md5ctx, &t, 2);
! 459: MD5_Update(&md5ctx, secret, slen);
! 460: MD5_Update(&md5ctx, randvec, randvec_len);
! 461: MD5_Final(hash, &md5ctx);
! 462: for (l = 0; l <= (2 + alen - 1)/MD5_DIGEST_LENGTH; l++) {
! 463: MD5_Init(&md5ctx);
! 464: MD5_Update(&md5ctx, secret, slen);
! 465: MD5_Update(&md5ctx, data + 6 + l*MD5_DIGEST_LENGTH, MD5_DIGEST_LENGTH);
! 466: MD5_Final(nhash, &md5ctx);
! 467: for (k = 0;
! 468: k < MD5_DIGEST_LENGTH &&
! 469: (l*MD5_DIGEST_LENGTH+k) < (alen - 6);
! 470: k++) {
! 471: data[6 + l*MD5_DIGEST_LENGTH + k] ^=
! 472: hash[k];
! 473: }
! 474: memcpy(hash, nhash, sizeof(hash));
! 475: }
! 476: olen = (data[6] << 8) + data[7] + 6;
! 477: if ((olen < 6) || (olen > (alen - 2)))
! 478: goto bogus;
! 479:
! 480: if (ppp_l2tp_avp_list_append(list,
! 481: (hdr[0] & AVP_MANDATORY) != 0, hdr[1], hdr[2],
! 482: data + 6 + 2, olen - 6) == -1)
! 483: goto fail;
! 484: } else {
! 485: if (ppp_l2tp_avp_list_append(list,
! 486: (hdr[0] & AVP_MANDATORY) != 0, hdr[1], hdr[2],
! 487: data + 6, alen - 6) == -1)
! 488: goto fail;
! 489: }
! 490:
! 491: skip:
! 492: /* Continue with next AVP */
! 493: data += alen;
! 494: dlen -= alen;
! 495: }
! 496:
! 497: /* Done */
! 498: return (list);
! 499:
! 500: bogus:
! 501: /* Invalid data */
! 502: errno = EILSEQ;
! 503: fail:
! 504: ppp_l2tp_avp_list_destroy(&list);
! 505: return (NULL);
! 506: }
! 507:
! 508: /***********************************************************************
! 509: AVP POINTERS METHODS
! 510: ***********************************************************************/
! 511:
! 512: /*
! 513: * Create an AVP pointers structure from an AVP list.
! 514: */
! 515: struct ppp_l2tp_avp_ptrs *
! 516: ppp_l2tp_avp_list2ptrs(const struct ppp_l2tp_avp_list *list)
! 517: {
! 518: struct ppp_l2tp_avp_ptrs *ptrs;
! 519: int i;
! 520:
! 521: /* Macro to allocate one pointer structure */
! 522: #define AVP_ALLOC(field) \
! 523: do { \
! 524: size_t _size = sizeof(*ptrs->field); \
! 525: \
! 526: if (_size < avp->vlen) \
! 527: _size = avp->vlen; \
! 528: _size += 16; \
! 529: Freee(ptrs->field); \
! 530: ptrs->field = Malloc(AVP_PTRS_MTYPE, _size); \
! 531: } while (0)
! 532:
! 533: /* Create new pointers structure */
! 534: ptrs = Malloc(AVP_PTRS_MTYPE, sizeof(*ptrs));
! 535:
! 536: /* Add recognized AVP's */
! 537: for (i = 0; i < list->length; i++) {
! 538: const struct ppp_l2tp_avp *const avp = &list->avps[i];
! 539: const u_char *const ptr8 = (u_char *)avp->value;
! 540: const u_int16_t *const ptr16 = (u_int16_t *)avp->value;
! 541: const u_int32_t *const ptr32 = (u_int32_t *)avp->value;
! 542:
! 543: if (avp->vendor != 0)
! 544: continue;
! 545: switch (avp->type) {
! 546: case AVP_MESSAGE_TYPE:
! 547: AVP_ALLOC(message);
! 548: ptrs->message->mesgtype = ntohs(ptr16[0]);
! 549: break;
! 550: case AVP_RESULT_CODE:
! 551: AVP_ALLOC(errresultcode);
! 552: ptrs->errresultcode->result = ntohs(ptr16[0]);
! 553: if (avp->vlen > 2)
! 554: ptrs->errresultcode->error = ntohs(ptr16[1]);
! 555: if (avp->vlen > 4) {
! 556: memcpy(ptrs->errresultcode->errmsg,
! 557: (char *)avp->value + 4, avp->vlen - 4);
! 558: }
! 559: break;
! 560: case AVP_PROTOCOL_VERSION:
! 561: AVP_ALLOC(protocol);
! 562: ptrs->protocol->version = ptr8[0];
! 563: ptrs->protocol->revision = ptr8[1];
! 564: break;
! 565: case AVP_FRAMING_CAPABILITIES:
! 566: AVP_ALLOC(framingcap);
! 567: ptrs->framingcap->sync =
! 568: (ntohl(ptr32[0]) & L2TP_FRAMING_SYNC) != 0;
! 569: ptrs->framingcap->async =
! 570: (ntohl(ptr32[0]) & L2TP_FRAMING_ASYNC) != 0;
! 571: break;
! 572: case AVP_BEARER_CAPABILITIES:
! 573: AVP_ALLOC(bearercap);
! 574: ptrs->bearercap->digital =
! 575: (ntohl(ptr32[0]) & L2TP_BEARER_DIGITAL) != 0;
! 576: ptrs->bearercap->analog =
! 577: (ntohl(ptr32[0]) & L2TP_BEARER_ANALOG) != 0;
! 578: break;
! 579: case AVP_TIE_BREAKER:
! 580: AVP_ALLOC(tiebreaker);
! 581: memcpy(ptrs->tiebreaker->value, avp->value, 8);
! 582: break;
! 583: case AVP_FIRMWARE_REVISION:
! 584: AVP_ALLOC(firmware);
! 585: ptrs->firmware->revision = ntohs(ptr16[0]);
! 586: break;
! 587: case AVP_HOST_NAME:
! 588: AVP_ALLOC(hostname);
! 589: memcpy(ptrs->hostname->hostname, avp->value, avp->vlen);
! 590: break;
! 591: case AVP_VENDOR_NAME:
! 592: AVP_ALLOC(vendor);
! 593: memcpy(ptrs->vendor->vendorname, avp->value, avp->vlen);
! 594: break;
! 595: case AVP_ASSIGNED_TUNNEL_ID:
! 596: AVP_ALLOC(tunnelid);
! 597: ptrs->tunnelid->id = ntohs(ptr16[0]);
! 598: break;
! 599: case AVP_RECEIVE_WINDOW_SIZE:
! 600: AVP_ALLOC(winsize);
! 601: ptrs->winsize->size = ntohs(ptr16[0]);
! 602: break;
! 603: case AVP_CHALLENGE:
! 604: AVP_ALLOC(challenge);
! 605: ptrs->challenge->length = avp->vlen;
! 606: memcpy(ptrs->challenge->value, avp->value, avp->vlen);
! 607: break;
! 608: case AVP_CAUSE_CODE:
! 609: AVP_ALLOC(causecode);
! 610: ptrs->causecode->causecode = ntohs(ptr16[0]);
! 611: ptrs->causecode->causemsg = ptr8[3];
! 612: memcpy(ptrs->causecode->message,
! 613: (char *)avp->value + 3, avp->vlen - 3);
! 614: break;
! 615: case AVP_CHALLENGE_RESPONSE:
! 616: AVP_ALLOC(challengresp);
! 617: memcpy(ptrs->challengresp->value,
! 618: avp->value, avp->vlen);
! 619: break;
! 620: case AVP_ASSIGNED_SESSION_ID:
! 621: AVP_ALLOC(sessionid);
! 622: ptrs->sessionid->id = ntohs(ptr16[0]);
! 623: break;
! 624: case AVP_CALL_SERIAL_NUMBER:
! 625: AVP_ALLOC(serialnum);
! 626: ptrs->serialnum->serialnum = ntohl(ptr32[0]);
! 627: break;
! 628: case AVP_MINIMUM_BPS:
! 629: AVP_ALLOC(minbps);
! 630: ptrs->minbps->minbps = ntohl(ptr32[0]);
! 631: break;
! 632: case AVP_MAXIMUM_BPS:
! 633: AVP_ALLOC(maxbps);
! 634: ptrs->maxbps->maxbps = ntohl(ptr32[0]);
! 635: break;
! 636: case AVP_BEARER_TYPE:
! 637: AVP_ALLOC(bearer);
! 638: ptrs->bearer->digital =
! 639: (ntohl(ptr32[0]) & L2TP_BEARER_DIGITAL) != 0;
! 640: ptrs->bearer->analog =
! 641: (ntohl(ptr32[0]) & L2TP_BEARER_ANALOG) != 0;
! 642: break;
! 643: case AVP_FRAMING_TYPE:
! 644: AVP_ALLOC(framing);
! 645: ptrs->framing->sync =
! 646: (ntohl(ptr32[0]) & L2TP_FRAMING_SYNC) != 0;
! 647: ptrs->framing->async =
! 648: (ntohl(ptr32[0]) & L2TP_FRAMING_ASYNC) != 0;
! 649: break;
! 650: case AVP_CALLED_NUMBER:
! 651: AVP_ALLOC(callednum);
! 652: memcpy(ptrs->callednum->number, avp->value, avp->vlen);
! 653: break;
! 654: case AVP_CALLING_NUMBER:
! 655: AVP_ALLOC(callingnum);
! 656: memcpy(ptrs->callingnum->number, avp->value, avp->vlen);
! 657: break;
! 658: case AVP_SUB_ADDRESS:
! 659: AVP_ALLOC(subaddress);
! 660: memcpy(ptrs->subaddress->number, avp->value, avp->vlen);
! 661: break;
! 662: case AVP_TX_CONNECT_SPEED:
! 663: AVP_ALLOC(txconnect);
! 664: ptrs->txconnect->bps = ntohl(ptr32[0]);
! 665: break;
! 666: case AVP_PHYSICAL_CHANNEL_ID:
! 667: AVP_ALLOC(channelid);
! 668: ptrs->channelid->channel = ntohl(ptr32[0]);
! 669: break;
! 670: case AVP_INITIAL_RECV_CONFREQ:
! 671: AVP_ALLOC(recvlcp);
! 672: ptrs->recvlcp->length = avp->vlen;
! 673: memcpy(ptrs->recvlcp->data, avp->value, avp->vlen);
! 674: break;
! 675: case AVP_LAST_SENT_CONFREQ:
! 676: AVP_ALLOC(lastsendlcp);
! 677: ptrs->lastsendlcp->length = avp->vlen;
! 678: memcpy(ptrs->lastsendlcp->data, avp->value, avp->vlen);
! 679: break;
! 680: case AVP_LAST_RECV_CONFREQ:
! 681: AVP_ALLOC(lastrecvlcp);
! 682: ptrs->lastrecvlcp->length = avp->vlen;
! 683: memcpy(ptrs->lastrecvlcp->data, avp->value, avp->vlen);
! 684: break;
! 685: case AVP_PROXY_AUTHEN_TYPE:
! 686: AVP_ALLOC(proxyauth);
! 687: ptrs->proxyauth->type = ntohs(ptr16[0]);
! 688: break;
! 689: case AVP_PROXY_AUTHEN_NAME:
! 690: AVP_ALLOC(proxyname);
! 691: ptrs->proxyname->length = avp->vlen;
! 692: memcpy(ptrs->proxyname->data, avp->value, avp->vlen);
! 693: break;
! 694: case AVP_PROXY_AUTHEN_CHALLENGE:
! 695: AVP_ALLOC(proxychallenge);
! 696: ptrs->proxychallenge->length = avp->vlen;
! 697: memcpy(ptrs->proxychallenge->data,
! 698: avp->value, avp->vlen);
! 699: break;
! 700: case AVP_PROXY_AUTHEN_ID:
! 701: AVP_ALLOC(proxyid);
! 702: ptrs->proxyid->id = ntohs(ptr16[0]);
! 703: break;
! 704: case AVP_PROXY_AUTHEN_RESPONSE:
! 705: AVP_ALLOC(proxyres);
! 706: ptrs->proxyres->length = avp->vlen;
! 707: memcpy(ptrs->proxyres->data, avp->value, avp->vlen);
! 708: break;
! 709: case AVP_CALL_ERRORS:
! 710: {
! 711: u_int32_t vals[6];
! 712:
! 713: memcpy(&vals, &ptr16[1], sizeof(vals));
! 714: AVP_ALLOC(callerror);
! 715: ptrs->callerror->crc = ntohl(vals[0]);
! 716: ptrs->callerror->frame = ntohl(vals[1]);
! 717: ptrs->callerror->overrun = ntohl(vals[2]);
! 718: ptrs->callerror->buffer = ntohl(vals[3]);
! 719: ptrs->callerror->timeout = ntohl(vals[4]);
! 720: ptrs->callerror->alignment = ntohl(vals[5]);
! 721: break;
! 722: }
! 723: case AVP_ACCM:
! 724: {
! 725: u_int32_t vals[2];
! 726:
! 727: memcpy(&vals, &ptr16[1], sizeof(vals));
! 728: AVP_ALLOC(accm);
! 729: ptrs->accm->xmit = ntohl(vals[0]);
! 730: ptrs->accm->recv = ntohl(vals[1]);
! 731: break;
! 732: }
! 733: case AVP_PRIVATE_GROUP_ID:
! 734: AVP_ALLOC(groupid);
! 735: ptrs->groupid->length = avp->vlen;
! 736: memcpy(ptrs->groupid->data, avp->value, avp->vlen);
! 737: break;
! 738: case AVP_RX_CONNECT_SPEED:
! 739: AVP_ALLOC(rxconnect);
! 740: ptrs->rxconnect->bps = ntohl(ptr32[0]);
! 741: break;
! 742: case AVP_SEQUENCING_REQUIRED:
! 743: AVP_ALLOC(seqrequired);
! 744: break;
! 745: default:
! 746: break;
! 747: }
! 748: }
! 749:
! 750: /* Done */
! 751: return (ptrs);
! 752: }
! 753:
! 754: /*
! 755: * Destroy an AVP pointers structure.
! 756: */
! 757: void
! 758: ppp_l2tp_avp_ptrs_destroy(struct ppp_l2tp_avp_ptrs **ptrsp)
! 759: {
! 760: struct ppp_l2tp_avp_ptrs *const ptrs = *ptrsp;
! 761:
! 762: if (ptrs == NULL)
! 763: return;
! 764: Freee(ptrs->message);
! 765: Freee(ptrs->errresultcode);
! 766: Freee(ptrs->protocol);
! 767: Freee(ptrs->framingcap);
! 768: Freee(ptrs->bearercap);
! 769: Freee(ptrs->tiebreaker);
! 770: Freee(ptrs->firmware);
! 771: Freee(ptrs->hostname);
! 772: Freee(ptrs->vendor);
! 773: Freee(ptrs->tunnelid);
! 774: Freee(ptrs->sessionid);
! 775: Freee(ptrs->winsize);
! 776: Freee(ptrs->challenge);
! 777: Freee(ptrs->challengresp);
! 778: Freee(ptrs->causecode);
! 779: Freee(ptrs->serialnum);
! 780: Freee(ptrs->minbps);
! 781: Freee(ptrs->maxbps);
! 782: Freee(ptrs->bearer);
! 783: Freee(ptrs->framing);
! 784: Freee(ptrs->callednum);
! 785: Freee(ptrs->callingnum);
! 786: Freee(ptrs->subaddress);
! 787: Freee(ptrs->txconnect);
! 788: Freee(ptrs->rxconnect);
! 789: Freee(ptrs->channelid);
! 790: Freee(ptrs->groupid);
! 791: Freee(ptrs->recvlcp);
! 792: Freee(ptrs->lastsendlcp);
! 793: Freee(ptrs->lastrecvlcp);
! 794: Freee(ptrs->proxyauth);
! 795: Freee(ptrs->proxyname);
! 796: Freee(ptrs->proxychallenge);
! 797: Freee(ptrs->proxyid);
! 798: Freee(ptrs->proxyres);
! 799: Freee(ptrs->callerror);
! 800: Freee(ptrs->accm);
! 801: Freee(ptrs->seqrequired);
! 802: Freee(ptrs);
! 803: *ptrsp = NULL;
! 804: }
! 805:
! 806: /***********************************************************************
! 807: AVP DECODERS
! 808: ***********************************************************************/
! 809:
! 810: #define DECODE_INITIAL(t) \
! 811: void \
! 812: ppp_l2tp_avp_decode_ ## t(const struct ppp_l2tp_avp_info *info, \
! 813: const struct ppp_l2tp_avp *avp, char *buf, size_t bmax) \
! 814: { \
! 815: const struct ppp_l2tp_avp_list list \
! 816: = { 1, (struct ppp_l2tp_avp *)avp }; \
! 817: struct ppp_l2tp_avp_ptrs *ptrs; \
! 818: \
! 819: if ((ptrs = ppp_l2tp_avp_list2ptrs(&list)) == NULL) { \
! 820: snprintf(buf, bmax, \
! 821: "decode failed: %s", strerror(errno)); \
! 822: goto done; \
! 823: } \
! 824: strlcpy(buf, "", bmax);
! 825:
! 826: #define DECODE_FINAL \
! 827: done: \
! 828: ppp_l2tp_avp_ptrs_destroy(&ptrs); \
! 829: }
! 830:
! 831: #define DECODE_BYTES(p, len) \
! 832: do { \
! 833: int _i; \
! 834: \
! 835: for (_i = 0; _i < len; _i++) { \
! 836: snprintf(buf + strlen(buf), \
! 837: bmax - strlen(buf), "%02x", \
! 838: ((u_char *)p)[_i]); \
! 839: } \
! 840: } while (0);
! 841:
! 842: DECODE_INITIAL(MESSAGE_TYPE)
! 843: {
! 844: static const char *names[] = {
! 845: "?0?", "SCCRQ", "SCCRP", "SCCCN", "StopCCN", "?5?",
! 846: "HELLO", "OCRQ", "OCRP", "OCCN", "ICRQ", "ICRP",
! 847: "ICCN", "?13?", "CDN", "WEN", "SLI",
! 848: };
! 849:
! 850: if (ptrs->message->mesgtype > sizeof(names) / sizeof(*names)) {
! 851: snprintf(buf, bmax, "?%u?", ptrs->message->mesgtype);
! 852: goto done;
! 853: }
! 854: strlcpy(buf, names[ptrs->message->mesgtype], bmax);
! 855: }
! 856: DECODE_FINAL
! 857:
! 858: DECODE_INITIAL(RESULT_CODE)
! 859: snprintf(buf, bmax, "result=%u error=%u errmsg=\"",
! 860: ptrs->errresultcode->result, ptrs->errresultcode->error);
! 861: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 862: ptrs->errresultcode->errmsg, strlen(ptrs->errresultcode->errmsg));
! 863: strlcat(buf, "\"", bmax);
! 864: DECODE_FINAL
! 865:
! 866: DECODE_INITIAL(PROTOCOL_VERSION)
! 867: snprintf(buf, bmax, "%u.%u",
! 868: ptrs->protocol->version, ptrs->protocol->revision);
! 869: DECODE_FINAL
! 870:
! 871: DECODE_INITIAL(FRAMING_CAPABILITIES)
! 872: snprintf(buf, bmax, "sync=%u async=%u",
! 873: ptrs->framingcap->sync, ptrs->framingcap->async);
! 874: DECODE_FINAL
! 875:
! 876: DECODE_INITIAL(BEARER_CAPABILITIES)
! 877: snprintf(buf, bmax, "digital=%u analog=%u",
! 878: ptrs->bearercap->digital, ptrs->bearercap->analog);
! 879: DECODE_FINAL
! 880:
! 881: DECODE_INITIAL(TIE_BREAKER)
! 882: snprintf(buf, bmax, "%02x%02x%02x%02x%02x%02x%02x%02x",
! 883: ((u_char *)ptrs->tiebreaker->value)[0],
! 884: ((u_char *)ptrs->tiebreaker->value)[1],
! 885: ((u_char *)ptrs->tiebreaker->value)[2],
! 886: ((u_char *)ptrs->tiebreaker->value)[3],
! 887: ((u_char *)ptrs->tiebreaker->value)[4],
! 888: ((u_char *)ptrs->tiebreaker->value)[5],
! 889: ((u_char *)ptrs->tiebreaker->value)[6],
! 890: ((u_char *)ptrs->tiebreaker->value)[7]);
! 891: DECODE_FINAL
! 892:
! 893: DECODE_INITIAL(FIRMWARE_REVISION)
! 894: snprintf(buf, bmax, "0x%04x", ptrs->firmware->revision);
! 895: DECODE_FINAL
! 896:
! 897: DECODE_INITIAL(HOST_NAME)
! 898: strlcpy(buf, "\"", bmax);
! 899: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 900: ptrs->hostname->hostname, strlen(ptrs->hostname->hostname));
! 901: strlcat(buf, "\"", bmax);
! 902: DECODE_FINAL
! 903:
! 904: DECODE_INITIAL(VENDOR_NAME)
! 905: strlcpy(buf, "\"", bmax);
! 906: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 907: ptrs->vendor->vendorname, strlen(ptrs->vendor->vendorname));
! 908: strlcat(buf, "\"", bmax);
! 909: DECODE_FINAL
! 910:
! 911: DECODE_INITIAL(ASSIGNED_TUNNEL_ID)
! 912: snprintf(buf, bmax, "0x%04x", ptrs->tunnelid->id);
! 913: DECODE_FINAL
! 914:
! 915: DECODE_INITIAL(RECEIVE_WINDOW_SIZE)
! 916: snprintf(buf, bmax, "%u", ptrs->winsize->size);
! 917: DECODE_FINAL
! 918:
! 919: DECODE_INITIAL(CHALLENGE)
! 920: DECODE_BYTES(ptrs->challenge->value, ptrs->challenge->length)
! 921: DECODE_FINAL
! 922:
! 923: DECODE_INITIAL(CAUSE_CODE)
! 924: snprintf(buf, bmax, "causecode=0x%04x causemsg=0x%02x msg=\"",
! 925: ptrs->causecode->causecode, ptrs->causecode->causemsg);
! 926: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 927: ptrs->causecode->message, strlen(ptrs->causecode->message));
! 928: strlcat(buf, "\"", bmax);
! 929: DECODE_FINAL
! 930:
! 931: DECODE_INITIAL(CHALLENGE_RESPONSE)
! 932: DECODE_BYTES(ptrs->challengresp->value, 16)
! 933: DECODE_FINAL
! 934:
! 935: DECODE_INITIAL(ASSIGNED_SESSION_ID)
! 936: snprintf(buf, bmax, "0x%04x", ptrs->sessionid->id);
! 937: DECODE_FINAL
! 938:
! 939: DECODE_INITIAL(CALL_SERIAL_NUMBER)
! 940: snprintf(buf, bmax, "%u", ptrs->serialnum->serialnum);
! 941: DECODE_FINAL
! 942:
! 943: DECODE_INITIAL(MINIMUM_BPS)
! 944: snprintf(buf, bmax, "%u", ptrs->minbps->minbps);
! 945: DECODE_FINAL
! 946:
! 947: DECODE_INITIAL(MAXIMUM_BPS)
! 948: snprintf(buf, bmax, "%u", ptrs->maxbps->maxbps);
! 949: DECODE_FINAL
! 950:
! 951: DECODE_INITIAL(BEARER_TYPE)
! 952: snprintf(buf, bmax, "digital=%u analog=%u",
! 953: ptrs->bearer->digital, ptrs->bearer->analog);
! 954: DECODE_FINAL
! 955:
! 956: DECODE_INITIAL(FRAMING_TYPE)
! 957: snprintf(buf, bmax, "sync=%u async=%u",
! 958: ptrs->framing->sync, ptrs->framing->async);
! 959: DECODE_FINAL
! 960:
! 961: DECODE_INITIAL(CALLED_NUMBER)
! 962: strlcpy(buf, "\"", bmax);
! 963: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 964: ptrs->callednum->number, strlen(ptrs->callednum->number));
! 965: strlcat(buf, "\"", bmax);
! 966: DECODE_FINAL
! 967:
! 968: DECODE_INITIAL(CALLING_NUMBER)
! 969: strlcpy(buf, "\"", bmax);
! 970: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 971: ptrs->callingnum->number, strlen(ptrs->callingnum->number));
! 972: strlcat(buf, "\"", bmax);
! 973: DECODE_FINAL
! 974:
! 975: DECODE_INITIAL(SUB_ADDRESS)
! 976: strlcpy(buf, "\"", bmax);
! 977: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 978: ptrs->subaddress->number, strlen(ptrs->subaddress->number));
! 979: strlcat(buf, "\"", bmax);
! 980: DECODE_FINAL
! 981:
! 982: DECODE_INITIAL(TX_CONNECT_SPEED)
! 983: snprintf(buf, bmax, "%u", ptrs->txconnect->bps);
! 984: DECODE_FINAL
! 985:
! 986: DECODE_INITIAL(PHYSICAL_CHANNEL_ID)
! 987: snprintf(buf, bmax, "0x%08x", ptrs->channelid->channel);
! 988: DECODE_FINAL
! 989:
! 990: DECODE_INITIAL(INITIAL_RECV_CONFREQ)
! 991: // ppp_fsm_options_decode(lcp_opt_desc,
! 992: // ptrs->recvlcp->data, ptrs->recvlcp->length, buf, bmax);
! 993: DECODE_FINAL
! 994:
! 995: DECODE_INITIAL(LAST_SENT_CONFREQ)
! 996: // ppp_fsm_options_decode(lcp_opt_desc,
! 997: // ptrs->lastsendlcp->data, ptrs->lastsendlcp->length, buf, bmax);
! 998: DECODE_FINAL
! 999:
! 1000: DECODE_INITIAL(LAST_RECV_CONFREQ)
! 1001: // ppp_fsm_options_decode(lcp_opt_desc,
! 1002: // ptrs->lastrecvlcp->data, ptrs->lastrecvlcp->length, buf, bmax);
! 1003: DECODE_FINAL
! 1004:
! 1005: DECODE_INITIAL(PROXY_AUTHEN_TYPE)
! 1006: snprintf(buf, bmax, "%u", ptrs->proxyauth->type);
! 1007: DECODE_FINAL
! 1008:
! 1009: DECODE_INITIAL(PROXY_AUTHEN_NAME)
! 1010: strlcpy(buf, "\"", bmax);
! 1011: ppp_util_ascify(buf + strlen(buf), bmax - strlen(buf),
! 1012: ptrs->proxyname->data, strlen(ptrs->proxyname->data));
! 1013: strlcat(buf, "\"", bmax);
! 1014: DECODE_FINAL
! 1015:
! 1016: DECODE_INITIAL(PROXY_AUTHEN_CHALLENGE)
! 1017: DECODE_BYTES(ptrs->proxychallenge->data, ptrs->proxychallenge->length)
! 1018: DECODE_FINAL
! 1019:
! 1020: DECODE_INITIAL(PROXY_AUTHEN_ID)
! 1021: snprintf(buf, bmax, "%u", ptrs->proxyid->id);
! 1022: DECODE_FINAL
! 1023:
! 1024: DECODE_INITIAL(PROXY_AUTHEN_RESPONSE)
! 1025: DECODE_BYTES(ptrs->proxyres->data, ptrs->proxyres->length)
! 1026: DECODE_FINAL
! 1027:
! 1028: DECODE_INITIAL(CALL_ERRORS)
! 1029: snprintf(buf, bmax, "crc=%u frame=%u overrun=%u"
! 1030: "buffer=%u timeout=%u alignment=%u",
! 1031: ptrs->callerror->crc, ptrs->callerror->frame,
! 1032: ptrs->callerror->overrun, ptrs->callerror->buffer,
! 1033: ptrs->callerror->timeout, ptrs->callerror->alignment);
! 1034: DECODE_FINAL
! 1035:
! 1036: DECODE_INITIAL(ACCM)
! 1037: snprintf(buf, bmax, "xmit=0x%08x recv=0x%08x",
! 1038: ptrs->accm->xmit, ptrs->accm->recv);
! 1039: DECODE_FINAL
! 1040:
! 1041: DECODE_INITIAL(RANDOM_VECTOR)
! 1042: DECODE_BYTES(avp->value, avp->vlen)
! 1043: DECODE_FINAL
! 1044:
! 1045: DECODE_INITIAL(PRIVATE_GROUP_ID)
! 1046: DECODE_BYTES(ptrs->groupid->data, ptrs->groupid->length)
! 1047: DECODE_FINAL
! 1048:
! 1049: DECODE_INITIAL(RX_CONNECT_SPEED)
! 1050: snprintf(buf, bmax, "%u", ptrs->rxconnect->bps);
! 1051: DECODE_FINAL
! 1052:
! 1053: DECODE_INITIAL(SEQUENCING_REQUIRED)
! 1054: DECODE_FINAL
! 1055:
! 1056:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>