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