Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Jing Min Zhao | 4198 | 84.47% | 3 | 11.54% |
Eric Sesterhenn / Snakebyte | 472 | 9.50% | 3 | 11.54% |
Jan Engelhardt | 109 | 2.19% | 3 | 11.54% |
Harsha Sharma | 78 | 1.57% | 1 | 3.85% |
Linus Torvalds (pre-git) | 32 | 0.64% | 4 | 15.38% |
Patrick McHardy | 27 | 0.54% | 4 | 15.38% |
lena wang | 20 | 0.40% | 1 | 3.85% |
Stephen Hemminger | 18 | 0.36% | 1 | 3.85% |
Gustavo A. R. Silva | 6 | 0.12% | 1 | 3.85% |
Toby DiPasquale | 4 | 0.08% | 1 | 3.85% |
Varsha Rao | 3 | 0.06% | 1 | 3.85% |
Yonatan Goldschmidt | 1 | 0.02% | 1 | 3.85% |
David Sterba | 1 | 0.02% | 1 | 3.85% |
Thomas Gleixner | 1 | 0.02% | 1 | 3.85% |
Total | 4970 | 26 |
// SPDX-License-Identifier: GPL-2.0-only /* * BER and PER decoding library for H.323 conntrack/NAT module. * * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net> * * See nf_conntrack_helper_h323_asn1.h for details. */ #ifdef __KERNEL__ #include <linux/kernel.h> #else #include <stdio.h> #endif #include <linux/netfilter/nf_conntrack_h323_asn1.h> /* Trace Flag */ #ifndef H323_TRACE #define H323_TRACE 0 #endif #if H323_TRACE #define TAB_SIZE 4 #define IFTHEN(cond, act) if(cond){act;} #ifdef __KERNEL__ #define PRINT printk #else #define PRINT printf #endif #define FNAME(name) name, #else #define IFTHEN(cond, act) #define PRINT(fmt, args...) #define FNAME(name) #endif /* ASN.1 Types */ #define NUL 0 #define BOOL 1 #define OID 2 #define INT 3 #define ENUM 4 #define BITSTR 5 #define NUMSTR 6 #define NUMDGT 6 #define TBCDSTR 6 #define OCTSTR 7 #define PRTSTR 7 #define IA5STR 7 #define GENSTR 7 #define BMPSTR 8 #define SEQ 9 #define SET 9 #define SEQOF 10 #define SETOF 10 #define CHOICE 11 /* Constraint Types */ #define FIXD 0 /* #define BITS 1-8 */ #define BYTE 9 #define WORD 10 #define CONS 11 #define SEMI 12 #define UNCO 13 /* ASN.1 Type Attributes */ #define SKIP 0 #define STOP 1 #define DECODE 2 #define EXT 4 #define OPEN 8 #define OPT 16 /* ASN.1 Field Structure */ typedef struct field_t { #if H323_TRACE char *name; #endif unsigned char type; unsigned char sz; unsigned char lb; unsigned char ub; unsigned short attr; unsigned short offset; const struct field_t *fields; } field_t; /* Bit Stream */ struct bitstr { unsigned char *buf; unsigned char *beg; unsigned char *end; unsigned char *cur; unsigned int bit; }; /* Tool Functions */ #define INC_BIT(bs) if((++(bs)->bit)>7){(bs)->cur++;(bs)->bit=0;} #define INC_BITS(bs,b) if(((bs)->bit+=(b))>7){(bs)->cur+=(bs)->bit>>3;(bs)->bit&=7;} #define BYTE_ALIGN(bs) if((bs)->bit){(bs)->cur++;(bs)->bit=0;} static unsigned int get_len(struct bitstr *bs); static unsigned int get_bit(struct bitstr *bs); static unsigned int get_bits(struct bitstr *bs, unsigned int b); static unsigned int get_bitmap(struct bitstr *bs, unsigned int b); static unsigned int get_uint(struct bitstr *bs, int b); /* Decoder Functions */ static int decode_nul(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_bool(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_oid(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_int(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_enum(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_bitstr(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_numstr(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_octstr(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_bmpstr(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_seq(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_seqof(struct bitstr *bs, const struct field_t *f, char *base, int level); static int decode_choice(struct bitstr *bs, const struct field_t *f, char *base, int level); /* Decoder Functions Vector */ typedef int (*decoder_t)(struct bitstr *, const struct field_t *, char *, int); static const decoder_t Decoders[] = { decode_nul, decode_bool, decode_oid, decode_int, decode_enum, decode_bitstr, decode_numstr, decode_octstr, decode_bmpstr, decode_seq, decode_seqof, decode_choice, }; /* * H.323 Types */ #include "nf_conntrack_h323_types.c" /* * Functions */ /* Assume bs is aligned && v < 16384 */ static unsigned int get_len(struct bitstr *bs) { unsigned int v; v = *bs->cur++; if (v & 0x80) { v &= 0x3f; v <<= 8; v += *bs->cur++; } return v; } static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits) { bits += bs->bit; bytes += bits / BITS_PER_BYTE; if (bits % BITS_PER_BYTE > 0) bytes++; if (bs->cur + bytes > bs->end) return 1; return 0; } static unsigned int get_bit(struct bitstr *bs) { unsigned int b = (*bs->cur) & (0x80 >> bs->bit); INC_BIT(bs); return b; } /* Assume b <= 8 */ static unsigned int get_bits(struct bitstr *bs, unsigned int b) { unsigned int v, l; v = (*bs->cur) & (0xffU >> bs->bit); l = b + bs->bit; if (l < 8) { v >>= 8 - l; bs->bit = l; } else if (l == 8) { bs->cur++; bs->bit = 0; } else { /* l > 8 */ v <<= 8; v += *(++bs->cur); v >>= 16 - l; bs->bit = l - 8; } return v; } /* Assume b <= 32 */ static unsigned int get_bitmap(struct bitstr *bs, unsigned int b) { unsigned int v, l, shift, bytes; if (!b) return 0; l = bs->bit + b; if (l < 8) { v = (unsigned int)(*bs->cur) << (bs->bit + 24); bs->bit = l; } else if (l == 8) { v = (unsigned int)(*bs->cur++) << (bs->bit + 24); bs->bit = 0; } else { for (bytes = l >> 3, shift = 24, v = 0; bytes; bytes--, shift -= 8) v |= (unsigned int)(*bs->cur++) << shift; if (l < 32) { v |= (unsigned int)(*bs->cur) << shift; v <<= bs->bit; } else if (l > 32) { v <<= bs->bit; v |= (*bs->cur) >> (8 - bs->bit); } bs->bit = l & 0x7; } v &= 0xffffffff << (32 - b); return v; } /* * Assume bs is aligned and sizeof(unsigned int) == 4 */ static unsigned int get_uint(struct bitstr *bs, int b) { unsigned int v = 0; switch (b) { case 4: v |= *bs->cur++; v <<= 8; fallthrough; case 3: v |= *bs->cur++; v <<= 8; fallthrough; case 2: v |= *bs->cur++; v <<= 8; fallthrough; case 1: v |= *bs->cur++; break; } return v; } static int decode_nul(struct bitstr *bs, const struct field_t *f, char *base, int level) { PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); return H323_ERROR_NONE; } static int decode_bool(struct bitstr *bs, const struct field_t *f, char *base, int level) { PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); INC_BIT(bs); if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_oid(struct bitstr *bs, const struct field_t *f, char *base, int level) { int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 1, 0)) return H323_ERROR_BOUND; len = *bs->cur++; bs->cur += len; if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_int(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int len; PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); switch (f->sz) { case BYTE: /* Range == 256 */ BYTE_ALIGN(bs); bs->cur++; break; case WORD: /* 257 <= Range <= 64K */ BYTE_ALIGN(bs); bs->cur += 2; break; case CONS: /* 64K < Range < 4G */ if (nf_h323_error_boundary(bs, 0, 2)) return H323_ERROR_BOUND; len = get_bits(bs, 2) + 1; BYTE_ALIGN(bs); if (base && (f->attr & DECODE)) { /* timeToLive */ unsigned int v = get_uint(bs, len) + f->lb; PRINT(" = %u", v); *((unsigned int *)(base + f->offset)) = v; } bs->cur += len; break; case UNCO: BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); bs->cur += len; break; default: /* 2 <= Range <= 255 */ INC_BITS(bs, f->sz); break; } PRINT("\n"); if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_enum(struct bitstr *bs, const struct field_t *f, char *base, int level) { PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); if ((f->attr & EXT) && get_bit(bs)) { INC_BITS(bs, 7); } else { INC_BITS(bs, f->sz); } if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_bitstr(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); BYTE_ALIGN(bs); switch (f->sz) { case FIXD: /* fixed length > 16 */ len = f->lb; break; case WORD: /* 2-byte length */ if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = (*bs->cur++) << 8; len += (*bs->cur++) + f->lb; break; case SEMI: if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); break; default: len = 0; break; } bs->cur += len >> 3; bs->bit = len & 7; if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_numstr(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); /* 2 <= Range <= 255 */ if (nf_h323_error_boundary(bs, 0, f->sz)) return H323_ERROR_BOUND; len = get_bits(bs, f->sz) + f->lb; BYTE_ALIGN(bs); INC_BITS(bs, (len << 2)); if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_octstr(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int len; PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); switch (f->sz) { case FIXD: /* Range == 1 */ if (f->lb > 2) { BYTE_ALIGN(bs); if (base && (f->attr & DECODE)) { /* The IP Address */ IFTHEN(f->lb == 4, PRINT(" = %d.%d.%d.%d:%d", bs->cur[0], bs->cur[1], bs->cur[2], bs->cur[3], bs->cur[4] * 256 + bs->cur[5])); *((unsigned int *)(base + f->offset)) = bs->cur - bs->buf; } } len = f->lb; break; case BYTE: /* Range == 256 */ BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 1, 0)) return H323_ERROR_BOUND; len = (*bs->cur++) + f->lb; break; case SEMI: BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs) + f->lb; break; default: /* 2 <= Range <= 255 */ if (nf_h323_error_boundary(bs, 0, f->sz)) return H323_ERROR_BOUND; len = get_bits(bs, f->sz) + f->lb; BYTE_ALIGN(bs); break; } bs->cur += len; PRINT("\n"); if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_bmpstr(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int len; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); switch (f->sz) { case BYTE: /* Range == 256 */ BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 1, 0)) return H323_ERROR_BOUND; len = (*bs->cur++) + f->lb; break; default: /* 2 <= Range <= 255 */ if (nf_h323_error_boundary(bs, 0, f->sz)) return H323_ERROR_BOUND; len = get_bits(bs, f->sz) + f->lb; BYTE_ALIGN(bs); break; } bs->cur += len << 1; if (nf_h323_error_boundary(bs, 0, 0)) return H323_ERROR_BOUND; return H323_ERROR_NONE; } static int decode_seq(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int ext, bmp, i, opt, len = 0, bmp2, bmp2_len; int err; const struct field_t *son; unsigned char *beg = NULL; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); /* Decode? */ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; /* Extensible? */ if (nf_h323_error_boundary(bs, 0, 1)) return H323_ERROR_BOUND; ext = (f->attr & EXT) ? get_bit(bs) : 0; /* Get fields bitmap */ if (nf_h323_error_boundary(bs, 0, f->sz)) return H323_ERROR_BOUND; if (f->sz > 32) return H323_ERROR_RANGE; bmp = get_bitmap(bs, f->sz); if (base) *(unsigned int *)base = bmp; /* Decode the root components */ for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) { if (son->attr & STOP) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); return H323_ERROR_STOP; } if (son->attr & OPT) { /* Optional component */ if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */ continue; } /* Decode */ if (son->attr & OPEN) { /* Open field */ if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; if (!base || !(son->attr & DECODE)) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); bs->cur += len; continue; } beg = bs->cur; /* Decode */ if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < H323_ERROR_NONE) return err; } /* No extension? */ if (!ext) return H323_ERROR_NONE; /* Get the extension bitmap */ if (nf_h323_error_boundary(bs, 0, 7)) return H323_ERROR_BOUND; bmp2_len = get_bits(bs, 7) + 1; if (nf_h323_error_boundary(bs, 0, bmp2_len)) return H323_ERROR_BOUND; if (bmp2_len > 32) return H323_ERROR_RANGE; bmp2 = get_bitmap(bs, bmp2_len); bmp |= bmp2 >> f->sz; if (base) *(unsigned int *)base = bmp; BYTE_ALIGN(bs); /* Decode the extension components */ for (opt = 0; opt < bmp2_len; opt++, i++, son++) { /* Check Range */ if (i >= f->ub) { /* Newer Version? */ if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; bs->cur += len; continue; } if (son->attr & STOP) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); return H323_ERROR_STOP; } if (!((0x80000000 >> opt) & bmp2)) /* Not present */ continue; if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; if (!base || !(son->attr & DECODE)) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); bs->cur += len; continue; } beg = bs->cur; if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; } return H323_ERROR_NONE; } static int decode_seqof(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int count, effective_count = 0, i, len = 0; int err; const struct field_t *son; unsigned char *beg = NULL; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); /* Decode? */ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; /* Decode item count */ switch (f->sz) { case BYTE: BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 1, 0)) return H323_ERROR_BOUND; count = *bs->cur++; break; case WORD: BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; count = *bs->cur++; count <<= 8; count += *bs->cur++; break; case SEMI: BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; count = get_len(bs); break; default: if (nf_h323_error_boundary(bs, 0, f->sz)) return H323_ERROR_BOUND; count = get_bits(bs, f->sz); break; } count += f->lb; /* Write Count */ if (base) { effective_count = count > f->ub ? f->ub : count; *(unsigned int *)base = effective_count; base += sizeof(unsigned int); } /* Decode nested field */ son = f->fields; if (base) base -= son->offset; for (i = 0; i < count; i++) { if (son->attr & OPEN) { BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; if (!base || !(son->attr & DECODE)) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); bs->cur += len; continue; } beg = bs->cur; if ((err = (Decoders[son->type]) (bs, son, i < effective_count ? base : NULL, level + 1)) < H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; } else if ((err = (Decoders[son->type]) (bs, son, i < effective_count ? base : NULL, level + 1)) < H323_ERROR_NONE) return err; if (base) base += son->offset; } return H323_ERROR_NONE; } static int decode_choice(struct bitstr *bs, const struct field_t *f, char *base, int level) { unsigned int type, ext, len = 0; int err; const struct field_t *son; unsigned char *beg = NULL; PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); /* Decode? */ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; /* Decode the choice index number */ if (nf_h323_error_boundary(bs, 0, 1)) return H323_ERROR_BOUND; if ((f->attr & EXT) && get_bit(bs)) { ext = 1; if (nf_h323_error_boundary(bs, 0, 7)) return H323_ERROR_BOUND; type = get_bits(bs, 7) + f->lb; } else { ext = 0; if (nf_h323_error_boundary(bs, 0, f->sz)) return H323_ERROR_BOUND; type = get_bits(bs, f->sz); if (type >= f->lb) return H323_ERROR_RANGE; } /* Write Type */ if (base) *(unsigned int *)base = type; /* Check Range */ if (type >= f->ub) { /* Newer version? */ BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; bs->cur += len; return H323_ERROR_NONE; } /* Transfer to son level */ son = &f->fields[type]; if (son->attr & STOP) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); return H323_ERROR_STOP; } if (ext || (son->attr & OPEN)) { BYTE_ALIGN(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) return H323_ERROR_BOUND; if (!base || !(son->attr & DECODE)) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); bs->cur += len; return H323_ERROR_NONE; } beg = bs->cur; if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < H323_ERROR_NONE) return err; return H323_ERROR_NONE; } int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage *ras) { static const struct field_t ras_message = { FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT, 0, _RasMessage }; struct bitstr bs; bs.buf = bs.beg = bs.cur = buf; bs.end = buf + sz; bs.bit = 0; return decode_choice(&bs, &ras_message, (char *) ras, 0); } static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg, size_t sz, H323_UserInformation *uuie) { static const struct field_t h323_userinformation = { FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT, 0, _H323_UserInformation }; struct bitstr bs; bs.buf = buf; bs.beg = bs.cur = beg; bs.end = beg + sz; bs.bit = 0; return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0); } int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, MultimediaSystemControlMessage * mscm) { static const struct field_t multimediasystemcontrolmessage = { FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4, DECODE | EXT, 0, _MultimediaSystemControlMessage }; struct bitstr bs; bs.buf = bs.beg = bs.cur = buf; bs.end = buf + sz; bs.bit = 0; return decode_choice(&bs, &multimediasystemcontrolmessage, (char *) mscm, 0); } int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931) { unsigned char *p = buf; int len; if (!p || sz < 1) return H323_ERROR_BOUND; /* Protocol Discriminator */ if (*p != 0x08) { PRINT("Unknown Protocol Discriminator\n"); return H323_ERROR_RANGE; } p++; sz--; /* CallReferenceValue */ if (sz < 1) return H323_ERROR_BOUND; len = *p++; sz--; if (sz < len) return H323_ERROR_BOUND; p += len; sz -= len; /* Message Type */ if (sz < 2) return H323_ERROR_BOUND; q931->MessageType = *p++; sz--; PRINT("MessageType = %02X\n", q931->MessageType); if (*p & 0x80) { p++; sz--; } /* Decode Information Elements */ while (sz > 0) { if (*p == 0x7e) { /* UserUserIE */ if (sz < 3) break; p++; len = *p++ << 8; len |= *p++; sz -= 3; if (sz < len) break; p++; len--; return DecodeH323_UserInformation(buf, p, len, &q931->UUIE); } p++; sz--; if (sz < 1) break; len = *p++; sz--; if (sz < len) break; p += len; sz -= len; } PRINT("Q.931 UUIE not found\n"); return H323_ERROR_BOUND; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1