/** * Pre-print macro expression to be expanded. * @param mb macro expansion state * @param s current expansion string * @param se end of string */ static void printMacro(MacroBuf mb, const char * s, const char * se) { const char *senl; const char *ellipsis; int choplen; if (s >= se) { /* XXX just in case */ fprintf(stderr, _("%3d>%*s(empty)"), mb->depth, (2 * mb->depth + 1), ""); return; } if (s[-1] == '{') s--; /* Print only to first end-of-line (or end-of-string). */ for (senl = se; *senl && !iseol(*senl); senl++) {}; /* Limit trailing non-trace output */ choplen = 61 - (2 * mb->depth); if ((senl - s) > choplen) { senl = s + choplen; ellipsis = "..."; } else ellipsis = ""; /* Substitute caret at end-of-macro position */ fprintf(stderr, "%3d>%*s%%%.*s^", mb->depth, (2 * mb->depth + 1), "", (int)(se - s), s); if (se[1] != '\0' && (senl - (se+1)) > 0) fprintf(stderr, "%-.*s%s", (int)(senl - (se+1)), se+1, ellipsis); fprintf(stderr, "\n"); }
/** * Post-print expanded macro expression. * @param mb macro expansion state * @param t current expansion string result * @param te end of string */ static void printExpansion(MacroBuf mb, const char * t, const char * te) { const char *ellipsis; int choplen; if (!(te > t)) { rpmlog(RPMLOG_DEBUG, _("%3d<%*s(empty)\n"), mb->depth, (2 * mb->depth + 1), ""); return; } /* Shorten output which contains newlines */ while (te > t && iseol(te[-1])) te--; ellipsis = ""; if (mb->depth > 0) { const char *tenl; /* Skip to last line of expansion */ while ((tenl = strchr(t, '\n')) && tenl < te) t = ++tenl; /* Limit expand output */ choplen = 61 - (2 * mb->depth); if ((te - t) > choplen) { te = t + choplen; ellipsis = "..."; } } rpmlog(RPMLOG_DEBUG,"%3d<%*s", mb->depth, (2 * mb->depth + 1), ""); if (te > t) rpmlog(RPMLOG_DEBUG, "%.*s%s", (int)(te - t), t, ellipsis); rpmlog(RPMLOG_DEBUG, "\n"); }
/** * Expand output of shell command into target buffer. * @param mb macro expansion state * @param cmd shell command * @param clen no. bytes in shell command * @return result of expansion */ static int doShellEscape(MacroBuf mb, const char * cmd, size_t clen) { char *buf = NULL; FILE *shf; int rc = 0; int c; rc = expandThis(mb, cmd, clen, &buf); if (rc) goto exit; if ((shf = popen(buf, "r")) == NULL) { rc = 1; goto exit; } size_t tpos = mb->tpos; while((c = fgetc(shf)) != EOF) { mbAppend(mb, c); } (void) pclose(shf); /* Delete trailing \r \n */ while (mb->tpos > tpos && iseol(mb->buf[mb->tpos-1])) { mb->buf[--mb->tpos] = '\0'; mb->nb++; } exit: _free(buf); return rc; }
/** * Parse (and execute) macro undefinition. * @param mc macro context * @param se macro name to undefine * @param slen length of se argument * @return address to continue parsing */ static const char * doUndefine(rpmMacroContext mc, const char * se, size_t slen) { const char *s = se; char *buf = xmalloc(slen + 1); char *n = buf, *ne = n; int c; COPYNAME(ne, s, c); /* Move scan over body */ while (iseol(*s)) s++; se = s; /* Names must start with alphabetic or _ and be at least 3 chars */ if (!((c = *n) && (risalpha(c) || c == '_') && (ne - n) > 2)) { rpmlog(RPMLOG_ERR, _("Macro %%%s has illegal name (%%undefine)\n"), n); goto exit; } popMacro(mc, n); exit: _free(buf); return se; }
static unsigned char * pnm_read_white(fz_context *ctx, unsigned char *p, unsigned char *e, int single_line) { if (e - p < 1) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot parse whitespace in pnm image"); if (single_line) { if (!iswhiteeol(*p) && *p != '#') fz_throw(ctx, FZ_ERROR_GENERIC, "expected whitespace/comment in pnm image"); while (p < e && iswhite(*p)) p++; if (p < e && *p == '#') while (p < e && !iseol(*p)) p++; if (p < e && iseol(*p)) p++; } else { if (!iswhiteeol(*p) && *p != '#') fz_throw(ctx, FZ_ERROR_GENERIC, "expected whitespace in pnm image"); while (p < e && iswhiteeol(*p)) p++; while (p < e && *p == '#') { while (p < e && !iseol(*p)) p++; if (p < e && iseol(*p)) p++; while (p < e && iswhiteeol(*p)) p++; if (p < e && iseol(*p)) p++; } } return p; }
static void skipeol(int fd) { char c; while (read(fd, &c, 1) == 1) { if (iseol(c)) break; } }
int handle_auth_parameter(str* line, ssize_t offset) { const char* ptr; ptr = skipspace(line->s + offset); /* No parameter, so just pass it through. */ if (iseol(*ptr)) return 0; if (strncasecmp(ptr, "LOGIN", 5) == 0) { if (ptr[5] == ' ' && !iseol(*(ptr = skipspace(ptr + 5)))) handle_auth_login_response(line, ptr - line->s); else saw_auth_login = 1; } else if (strncasecmp(ptr, "PLAIN", 5) == 0) { if (ptr[5] == ' ' && !iseol(*(ptr = skipspace(ptr + 5)))) handle_auth_plain_response(line, ptr - line->s); else saw_auth_plain = 1; } return 1; }
/** * fgets(3) analogue that reads \ continuations. Last newline always trimmed. * @param buf input buffer * @param size inbut buffer size (bytes) * @param f file handle * @return buffer, or NULL on end-of-file */ static char * rdcl(char * buf, size_t size, FILE *f) { char *q = buf - 1; /* initialize just before buffer. */ size_t nb = 0; size_t nread = 0; int pc = 0, bc = 0; char *p = buf; if (f != NULL) do { *(++q) = '\0'; /* terminate and move forward. */ if (fgets(q, size, f) == NULL) /* read next line. */ break; nb = strlen(q); nread += nb; /* trim trailing \r and \n */ for (q += nb - 1; nb > 0 && iseol(*q); q--) nb--; for (; p <= q; p++) { switch (*p) { case '\\': switch (*(p+1)) { case '\0': break; default: p++; break; } break; case '%': switch (*(p+1)) { case '{': p++, bc++; break; case '(': p++, pc++; break; case '%': p++; break; } break; case '{': if (bc > 0) bc++; break; case '}': if (bc > 0) bc--; break; case '(': if (pc > 0) pc++; break; case ')': if (pc > 0) pc--; break; } } if (nb == 0 || (*q != '\\' && !bc && !pc) || *(q+1) == '\0') { *(++q) = '\0'; /* trim trailing \r, \n */ break; } q++; p++; nb++; /* copy newline too */ size -= nb; if (*q == '\r') /* XXX avoid \r madness */ *q = '\n'; } while (size > 0); return (nread > 0 ? buf : NULL); }
/** * Expand output of shell command into target buffer. * @param mb macro expansion state * @param cmd shell command * @param clen no. bytes in shell command * @return result of expansion */ static int doShellEscape(MacroBuf mb, const char * cmd, size_t clen) { size_t blen = MACROBUFSIZ + clen; char *buf = xmalloc(blen); FILE *shf; int rc = 0; int c; strncpy(buf, cmd, clen); buf[clen] = '\0'; rc = expandU(mb, buf, blen); if (rc) goto exit; if ((shf = popen(buf, "r")) == NULL) { rc = 1; goto exit; } while((c = fgetc(shf)) != EOF) { if (mb->nb > 1) { SAVECHAR(mb, c); } } (void) pclose(shf); /* XXX delete trailing \r \n */ while (iseol(mb->t[-1])) { *(mb->t--) = '\0'; mb->nb++; } exit: _free(buf); return rc; }
/* * Mangle the "Transport:" header: * - Replace all occurences of "client_port=<spec>" * - Handle destination parameter * * In: * ct, ctinfo = conntrack context * skb = packet * tranoff = Transport header offset from TCP data * tranlen = Transport header length (incl. CRLF) * rport_lo = replacement low port (host endian) * rport_hi = replacement high port (host endian) * * Returns packet size difference. * * Assumes that a complete transport header is present, ending with CR or LF */ static int rtsp_mangle_tran(enum ip_conntrack_info ctinfo, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) unsigned int protoff, #endif struct nf_conntrack_expect* rtp_exp, struct nf_conntrack_expect* rtcp_exp, struct ip_ct_rtsp_expect* prtspexp, struct sk_buff* skb, uint tranoff, uint tranlen) { char* ptcp; uint tcplen; char* ptran; char rbuf1[16]; /* Replacement buffer (one port) */ uint rbuf1len; /* Replacement len (one port) */ char rbufa[16]; /* Replacement buffer (all ports) */ uint rbufalen; /* Replacement len (all ports) */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) union nf_inet_addr newip; #else u_int32_t newip; #endif u_int16_t loport, hiport; uint off = 0; uint diff; /* Number of bytes we removed */ struct nf_conn *ct = rtp_exp->master; /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ struct nf_conntrack_tuple *rtp_t; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) char szextaddr[INET6_ADDRSTRLEN]; #else char szextaddr[INET_ADDRSTRLEN]; #endif uint extaddrlen; int is_stun; get_skb_tcpdata(skb, &ptcp, &tcplen); ptran = ptcp+tranoff; if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || tranlen < 10 || !iseol(ptran[tranlen-1]) || nf_strncasecmp(ptran, "Transport:", 10) != 0) { pr_info("sanity check failed\n"); return 0; } off += 10; SKIP_WSPACE(ptcp+tranoff, tranlen, off); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; rtp_t = &rtp_exp->tuple; rtp_t->dst.u3 = newip; if (rtcp_exp) { rtcp_exp->tuple.dst.u3 = newip; } extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip pr_debug("stunaddr=%s (auto)\n", szextaddr); #else newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; rtp_t = &rtp_exp->tuple; rtp_t->dst.u3.ip = newip; if (rtcp_exp) { rtcp_exp->tuple.dst.u3.ip = newip; } extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) : sprintf(szextaddr, "%pI4", &newip); pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); #endif hiport = 0; rbuf1len = rbufalen = 0; switch (prtspexp->pbtype) { case pb_single: for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ rtp_t->dst.u.udp.port = htons(loport); if (nf_ct_expect_related(rtp_exp) == 0) { pr_debug("using port %hu\n", loport); break; } } if (loport != 0) { rbuf1len = sprintf(rbuf1, "%hu", loport); rbufalen = sprintf(rbufa, "%hu", loport); } break; case pb_range: for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ rtp_t->dst.u.udp.port = htons(loport); if (nf_ct_expect_related(rtp_exp) != 0) { continue; } hiport = loport + 1; rtcp_exp->tuple.dst.u.udp.port = htons(hiport); if (nf_ct_expect_related(rtcp_exp) != 0) { nf_ct_unexpect_related(rtp_exp); continue; } /* FIXME: invalid print in case of ipv6 */ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", &rtp_exp->tuple.src.u3.ip, ntohs(rtp_exp->tuple.src.u.udp.port), ntohs(rtcp_exp->tuple.src.u.udp.port), &rtp_exp->tuple.dst.u3.ip, ntohs(rtp_exp->tuple.dst.u.udp.port), ntohs(rtcp_exp->tuple.dst.u.udp.port)); break; } if (loport != 0) { rbuf1len = sprintf(rbuf1, "%hu", loport); rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); } break; case pb_discon: for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ rtp_t->dst.u.udp.port = htons(loport); if (nf_ct_expect_related(rtp_exp) == 0) { pr_debug("using port %hu (1 of 2)\n", loport); break; } } for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ rtp_t->dst.u.udp.port = htons(hiport); if (nf_ct_expect_related(rtp_exp) == 0) { pr_debug("using port %hu (2 of 2)\n", hiport); break; } } if (loport != 0 && hiport != 0) { rbuf1len = sprintf(rbuf1, "%hu", loport); rbufalen = sprintf(rbufa, hiport == loport+1 ? "%hu-%hu":"%hu/%hu", loport, hiport); } break; } if (rbuf1len == 0) return 0; /* cannot get replacement port(s) */ /* Transport: tran;field;field=val,tran;field;field=val,... `off` is set to the start of Transport value from start of line */ while (off < tranlen) { uint saveoff; const char* pparamend; uint nextparamoff; pparamend = memchr(ptran+off, ',', tranlen-off); pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; nextparamoff = pparamend-ptran; /* * We pass over each param twice. On the first pass, we look for a * destination= field. It is handled by the security policy. If it * is present, allowed, and equal to our external address, we assume * that STUN is being used and we leave the client_port= field alone. */ is_stun = 0; saveoff = off; while (off < nextparamoff) { const char* pfieldend; uint nextfieldoff; pfieldend = memchr(ptran+off, ';', nextparamoff-off); nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) { if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) is_stun = 1; if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { uint dstoff = (ptran-ptcp)+off; uint dstlen = nextfieldoff-off; char* pdstrep = NULL; uint dstreplen = 0; diff = dstlen; if (dstact == DSTACT_AUTO && !is_stun) { pr_debug("RTSP: replace dst addr\n"); dstoff += 12; dstlen -= 13; pdstrep = szextaddr; dstreplen = extaddrlen; diff = nextfieldoff-off-13-extaddrlen; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, dstoff, dstlen, pdstrep, dstreplen)) { #else if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, dstoff, dstlen, pdstrep, dstreplen)) { #endif /* mangle failed, all we can do is bail */ nf_ct_unexpect_related(rtp_exp); if (rtcp_exp) nf_ct_unexpect_related(rtcp_exp); return 0; } get_skb_tcpdata(skb, &ptcp, &tcplen); ptran = ptcp+tranoff; tranlen -= diff; nextparamoff -= diff; nextfieldoff -= diff; } } off = nextfieldoff; } if (is_stun) continue; off = saveoff; while (off < nextparamoff) { const char* pfieldend; uint nextfieldoff; pfieldend = memchr(ptran+off, ';', nextparamoff-off); nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; if (strncmp(ptran+off, "client_port=", 12) == 0) { u_int16_t port; uint numlen; uint origoff; uint origlen; char* rbuf = rbuf1; uint rbuflen = rbuf1len; off += 12; origoff = (ptran-ptcp)+off; origlen = 0; numlen = nf_strtou16(ptran+off, &port); off += numlen; origlen += numlen; if (port != prtspexp->loport) { pr_debug("multiple ports found, port %hu ignored\n", port); } else { if (ptran[off] == '-' || ptran[off] == '/') { off++; origlen++; numlen = nf_strtou16(ptran+off, &port); off += numlen; origlen += numlen; rbuf = rbufa; rbuflen = rbufalen; } /* * note we cannot just memcpy() if the sizes are the same. * the mangle function does skb resizing, checks for a * cloned skb, and updates the checksums. * * parameter 4 below is offset from start of tcp data. */ diff = origlen-rbuflen; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, origoff, origlen, rbuf, rbuflen)) { #else if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, origoff, origlen, rbuf, rbuflen)) { #endif /* mangle failed, all we can do is bail */ nf_ct_unexpect_related(rtp_exp); if (rtcp_exp) nf_ct_unexpect_related(rtcp_exp); return 0; } get_skb_tcpdata(skb, &ptcp, &tcplen); ptran = ptcp+tranoff; tranlen -= diff; nextparamoff -= diff; nextfieldoff -= diff; } } off = nextfieldoff; } off = nextparamoff; } return 1; } static uint help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) unsigned int protoff, #endif unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp, struct nf_conntrack_expect* rtp_exp, struct nf_conntrack_expect* rtcp_exp) { char* ptcp; uint tcplen; uint hdrsoff; uint hdrslen; uint lineoff; uint linelen; uint off; int dir = CTINFO2DIR(ctinfo); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; #else __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; #endif //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); get_skb_tcpdata(skb, &ptcp, &tcplen); hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); hdrslen = matchlen; off = hdrsoff; pr_debug("NAT rtsp help_out\n"); while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { if (linelen == 0) break; if (off > hdrsoff+hdrslen) { pr_info("!! overrun !!"); break; } pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { uint oldtcplen = tcplen; pr_debug("hdr: Transport\n"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, prtspexp, skb, lineoff, linelen)) { #else if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, skb, lineoff, linelen)) { #endif pr_debug("hdr: Transport mangle failed"); break; } rtp_exp->expectfn = nf_nat_rtsp_expected; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) rtp_exp->saved_addr = saddr; #else rtp_exp->saved_ip = saddr; #endif rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); rtp_exp->dir = !dir; if (rtcp_exp) { rtcp_exp->expectfn = nf_nat_rtsp_expected; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) rtcp_exp->saved_addr = saddr; #else rtcp_exp->saved_ip = saddr; #endif rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); rtcp_exp->dir = !dir; } get_skb_tcpdata(skb, &ptcp, &tcplen); hdrslen -= (oldtcplen-tcplen); off -= (oldtcplen-tcplen); lineoff -= (oldtcplen-tcplen); linelen -= (oldtcplen-tcplen); pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); } } return NF_ACCEPT; } static unsigned int nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) unsigned int protoff, #endif unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp, struct nf_conntrack_expect* rtp_exp, struct nf_conntrack_expect* rtcp_exp) { int dir = CTINFO2DIR(ctinfo); int rc = NF_ACCEPT; switch (dir) { case IP_CT_DIR_ORIGINAL: #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, rtp_exp, rtcp_exp); #else rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, rtp_exp, rtcp_exp); #endif break; case IP_CT_DIR_REPLY: pr_debug("unmangle ! %u\n", ctinfo); /* XXX: unmangle */ rc = NF_ACCEPT; break; } //UNLOCK_BH(&ip_rtsp_lock); return rc; } static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) struct nf_nat_range range; #else struct nf_nat_ipv4_range range; #endif /* This must be a fresh one. */ BUG_ON(ct->status & IPS_NAT_DONE_MASK); /* For DST manip, map port here to where it's expected. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) range.min_proto = range.max_proto = exp->saved_proto; range.min_addr = range.max_addr = exp->saved_addr; #else range.min = range.max = exp->saved_proto; range.min_ip = range.max_ip = exp->saved_ip; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); #else range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); #endif /* Change src to where master sends to, but only if the connection * actually came from the same source. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &ct->master->tuplehash[exp->dir].tuple.src.u3)) { range.min_addr = range.max_addr = ct->master->tuplehash[!exp->dir].tuple.dst.u3; #else if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) range.flags = NF_NAT_RANGE_MAP_IPS; nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); #else range.flags = IP_NAT_RANGE_MAP_IPS; nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); #endif } } static void __exit fini(void) { rcu_assign_pointer(nf_nat_rtsp_hook, NULL); synchronize_net(); } static int __init init(void) { printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); BUG_ON(nf_nat_rtsp_hook); rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); if (stunaddr != NULL) extip = in_aton(stunaddr); if (destaction != NULL) { if (strcmp(destaction, "auto") == 0) dstact = DSTACT_AUTO; if (strcmp(destaction, "strip") == 0) dstact = DSTACT_STRIP; if (strcmp(destaction, "none") == 0) dstact = DSTACT_NONE; } return 0; }
/** * Parse (and execute) new macro definition. * @param mb macro expansion state * @param se macro definition to parse * @param slen length of se argument * @param level macro recursion level * @param expandbody should body be expanded? * @return address to continue parsing */ static const char * doDefine(MacroBuf mb, const char * se, size_t slen, int level, int expandbody) { const char *s = se; char *buf = xmalloc(slen + 3); /* Some leeway for termination issues... */ char *n = buf, *ne = n; char *o = NULL, *oe; char *b, *be, *ebody = NULL; int c; int oc = ')'; const char *sbody; /* as-is body start */ /* Copy name */ COPYNAME(ne, s, c); /* Copy opts (if present) */ oe = ne + 1; if (*s == '(') { s++; /* skip ( */ /* Options must be terminated with ')' */ if (strchr(s, ')')) { o = oe; COPYOPTS(oe, s, oc); s++; /* skip ) */ } else { rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated opts\n"), n); goto exit; } } /* Copy body, skipping over escaped newlines */ b = be = oe + 1; sbody = s; SKIPBLANK(s, c); if (c == '{') { /* XXX permit silent {...} grouping */ if ((se = matchchar(s, c, '}')) == NULL) { rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated body\n"), n); se = s; /* XXX W2DO? */ goto exit; } s++; /* XXX skip { */ strncpy(b, s, (se - s)); b[se - s] = '\0'; be += strlen(b); se++; /* XXX skip } */ s = se; /* move scan forward */ } else { /* otherwise free-field */ int bc = 0, pc = 0; while (*s && (bc || pc || !iseol(*s))) { switch (*s) { case '\\': switch (*(s+1)) { case '\0': break; default: s++; break; } break; case '%': switch (*(s+1)) { case '{': *be++ = *s++; bc++; break; case '(': *be++ = *s++; pc++; break; case '%': *be++ = *s++; break; } break; case '{': if (bc > 0) bc++; break; case '}': if (bc > 0) bc--; break; case '(': if (pc > 0) pc++; break; case ')': if (pc > 0) pc--; break; } *be++ = *s++; } *be = '\0'; if (bc || pc) { rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated body\n"), n); se = s; /* XXX W2DO? */ goto exit; } /* Trim trailing blanks/newlines */ while (--be >= b && (c = *be) && (isblank(c) || iseol(c))) {}; *(++be) = '\0'; /* one too far */ } /* Move scan over body */ while (iseol(*s)) s++; se = s; /* Names must start with alphabetic or _ and be at least 3 chars */ if (!((c = *n) && (risalpha(c) || c == '_') && (ne - n) > 2)) { rpmlog(RPMLOG_ERR, _("Macro %%%s has illegal name (%%define)\n"), n); goto exit; } if ((be - b) < 1) { rpmlog(RPMLOG_ERR, _("Macro %%%s has empty body\n"), n); goto exit; } if (!isblank(*sbody) && !(*sbody == '\\' && iseol(sbody[1]))) rpmlog(RPMLOG_WARNING, _("Macro %%%s needs whitespace before body\n"), n); if (expandbody) { if (expandThis(mb, b, 0, &ebody)) { rpmlog(RPMLOG_ERR, _("Macro %%%s failed to expand\n"), n); goto exit; } b = ebody; } pushMacro(mb->mc, n, o, b, (level - 1), ME_NONE); exit: _free(buf); _free(ebody); return se; }
BOOL FormatFile (LPTSTR pszName, LPTSTR pszText) { // Find the appropriate output filename // TCHAR szName[ MAX_PATH ]; lstrcpy (szName, pszName); LPTSTR pchSlash = NULL; for (LPTSTR pch = szName; *pch; ++pch) { if (*pch == TEXT('\\')) pchSlash = NULL; else if (*pch == TEXT('.')) pchSlash = pch; } if (pchSlash) lstrcpy (pchSlash, TEXT(".rtf")); else // (!pchSlash) lstrcat (szName, TEXT(".rtf")); // Open an output file handle // HANDLE hFile; if ((hFile = CreateFile (szName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) { printf ("failed to create %s; error %lu\n", szName, GetLastError()); return FALSE; } // Write the RTF prolog // char *pszPROLOG = "{\\rtf1\\ansi\\deff0\\deftab720\\ansicpg%lu\n" "{\\colortbl\\red0\\green0\\blue0;}\\pard"; char szProlog[ 1024 ]; wsprintf (szProlog, pszPROLOG, g::CodePage); DWORD dwWrote; WriteFile (hFile, szProlog, lstrlen(szProlog), &dwWrote, NULL); // Translate the file itself // BOOL fAllowCRLF = FALSE; BOOL fInFormatted = FALSE; size_t cFormatted = FALSE; LPTSTR pchNext = NULL; for (LPTSTR pchRead = pszText; pchRead && *pchRead; pchRead = pchNext) { while (iswhiteeol(*pchRead)) ++pchRead; if (!*pchRead) break; if (*pchRead == '<') { pchNext = &pchRead[1]; while (*pchNext && (*pchNext != '>')) ++pchNext; if (*pchNext == '>') ++pchNext; // If this was a "<p>", write an EOL. // If this was a "<d>", write paragraph-header formatting info. // If this was a "<?>", write an EOL. // if (tolower(pchRead[1]) == '?') { if (fAllowCRLF) WriteFile (hFile, "\r\n\\par ", lstrlen("\r\n\\par "), &dwWrote, NULL); } else if (tolower(pchRead[1]) == 'p') { if (fAllowCRLF) WriteFile (hFile, "\r\n\\par \r\n\\par ", lstrlen("\r\n\\par \r\n\\par "), &dwWrote, NULL); if (fInFormatted) { char *pszPLAIN = "\\plain\\fs20 "; WriteFile (hFile, pszPLAIN, lstrlen(pszPLAIN), &dwWrote, NULL); } fInFormatted = FALSE; } else if (tolower(pchRead[1]) == 'd') { if (fAllowCRLF) WriteFile (hFile, "\r\n\\par \r\n\\par ", lstrlen("\r\n\\par \r\n\\par "), &dwWrote, NULL); char *pszWrite; if ((++cFormatted) <= 2) pszWrite = "\\plain\\fs28\\b "; else // (cFormatted > 2) pszWrite = "\\plain\\fs24\\b "; WriteFile (hFile, pszWrite, lstrlen(pszWrite), &dwWrote, NULL); fInFormatted = TRUE; } } else // (*pchRead != '<') { pchNext = &pchRead[1]; while (*pchNext && (*pchNext != '<') && !iseol(*pchNext)) ++pchNext; LPTSTR pszEscaped; if ((pszEscaped = EscapeSpecialCharacters (pchRead, pchNext - pchRead)) == NULL) break; WriteFile (hFile, pszEscaped, lstrlen(pszEscaped), &dwWrote, NULL); fAllowCRLF = TRUE; } } // Write the RTF trailer // char *pszTRAILER = "\\par }"; WriteFile (hFile, pszTRAILER, lstrlen(pszTRAILER), &dwWrote, NULL); SetEndOfFile (hFile); CloseHandle (hFile); return TRUE; }
static pgeObjMtl *pgeObjLoadMaterial(const char *matname) { int fd = sceIoOpen(matname, PSP_O_RDONLY, 0777); if(fd < 0) return NULL; long filesize; filesize = sceIoLseek32(fd, 0, PSP_SEEK_END); sceIoLseek32(fd, 0, PSP_SEEK_SET); unsigned char *data = pgeMalloc(filesize); if(!data) return NULL; sceIoRead(fd, data, filesize); sceIoClose(fd); unsigned char *currentpos, *endpos; unsigned int position = 0; unsigned int numnewmtl = 0; unsigned int newmtlpos = 0, kapos = 0, kdpos = 0, kspos = 0, nspos = 0; char readbuffer[512]; currentpos = data; endpos = currentpos + filesize; while(currentpos != endpos) { position = 0; while((isdeadspace(*currentpos)) && (currentpos != endpos)) currentpos++; while((!iseol(*currentpos)) && (currentpos != endpos) && (position < 512)) { readbuffer[position++] = *currentpos; currentpos++; } readbuffer[position] = 0; if(strequal(readbuffer, "newmtl", &readbuffer[position], 6)) numnewmtl++; } // Allocate what we need pgeObjMtl *mtl = pgeMalloc(sizeof(pgeObjMtl)); if(!mtl) { pgeFree(data); return NULL; } mtl->materials = (pgeObjMtlEntry *)pgeMalloc(sizeof(pgeObjMtlEntry) * numnewmtl); if(!mtl->materials) { pgeFree(mtl); pgeFree(data); return NULL; } mtl->nummaterials = numnewmtl; // Read back through and populate currentpos = data; char namebuffer[128]; while(currentpos != endpos) { position = 0; while((isdeadspace(*currentpos)) && (currentpos != endpos)) currentpos++; while((!iseol(*currentpos)) && (currentpos != endpos) && (position < 512)) { readbuffer[position++] = *currentpos; currentpos++; } readbuffer[position] = 0; if(strequal(readbuffer, "newmtl", &readbuffer[position], 6)) { sscanf(readbuffer, "newmtl %s", namebuffer); mtl->materials[newmtlpos].name = pgeMalloc(strlen(namebuffer) + 1); if(!mtl->materials[newmtlpos].name) { pgeFree(mtl->materials); pgeFree(mtl); pgeFree(data); return NULL; } strcpy(mtl->materials[newmtlpos].name, namebuffer); newmtlpos++; } else if(strequal(readbuffer, "Ka", &readbuffer[position], 2)) { sscanf(readbuffer, "Ka %f %f %f", &mtl->materials[kapos].ambient[0], &mtl->materials[kapos].ambient[1], &mtl->materials[kapos].ambient[2]); kapos++; } else if(strequal(readbuffer, "Kd", &readbuffer[position], 2)) { sscanf(readbuffer, "Kd %f %f %f", &mtl->materials[kdpos].diffuse[0], &mtl->materials[kdpos].diffuse[1], &mtl->materials[kdpos].diffuse[2]); kdpos++; } else if(strequal(readbuffer, "Ks", &readbuffer[position], 2)) { sscanf(readbuffer, "Ks %f %f %f", &mtl->materials[kspos].specular[0], &mtl->materials[kspos].specular[1], &mtl->materials[kspos].specular[2]); kspos++; } else if(strequal(readbuffer, "Ns", &readbuffer[position], 2)) { sscanf(readbuffer, "Ns %f", &mtl->materials[nspos].shinyness); nspos++; } } return mtl; }
static pgeObj *pgeObjLoadInternal(unsigned char *buffer, unsigned int size) { typedef struct objVertex { float x, y, z; } objVertex; typedef objVertex objNormal; typedef struct objTexCoord { float u, v; } objTexCoord; typedef struct objTriangle { unsigned int vertex[3]; unsigned int normal[3]; unsigned int texcoord[3]; unsigned int color; } objTriangle; typedef struct objModel { unsigned int numVertex, numNormal, numTexCoord, numTriangle, numMaterial; objVertex *vertexArray; objNormal *normalArray; objTexCoord *texCoordArray; objTriangle *triangleArray; } objModel; objModel *model = pgeMalloc(sizeof(objModel)); pgeObjMtl *mtl = NULL; unsigned char *currentpos, *endpos; unsigned int position = 0; int vertpos = 0, normalpos = 0, texvertpos = 0, facepos = 0; char readbuffer[512]; char materialname[128]; currentpos = buffer; endpos = buffer + size; // Seek through file, counting number of entries we are interesting in while(currentpos != endpos) { position = 0; while((isdeadspace(*currentpos)) && (currentpos != endpos)) currentpos++; while((!iseol(*currentpos)) && (currentpos != endpos) && (position < 512)) { readbuffer[position++] = *currentpos; currentpos++; } readbuffer[position] = 0; if(strequal(readbuffer, "vn", &readbuffer[position], 2)) model->numNormal++; else if(strequal(readbuffer, "vt", &readbuffer[position], 2)) model->numTexCoord++; else if(strequal(readbuffer, "v", &readbuffer[position], 1)) model->numVertex++; else if(strequal(readbuffer, "f", &readbuffer[position], 1)) model->numTriangle++; else if(strequal(readbuffer, "mtllib", &readbuffer[position], 6)) model->numMaterial++; } // Allocate what we need if(model->numVertex > 0) { model->vertexArray = pgeMalloc(model->numVertex * sizeof(objVertex)); if(!model->vertexArray) { pgeFree(model); return NULL; } } if(model->numNormal > 0) { model->normalArray = pgeMalloc(model->numNormal * sizeof(objNormal)); if(!model->normalArray) { pgeFree(model->vertexArray); pgeFree(model); return NULL; } } if(model->numTexCoord > 0) { model->texCoordArray = pgeMalloc(model->numTexCoord * sizeof(objTexCoord)); if(!model->texCoordArray) { pgeFree(model->vertexArray); pgeFree(model->normalArray); pgeFree(model); return NULL; } } if(model->numTriangle > 0) { model->triangleArray = pgeMalloc(model->numTriangle * sizeof(objTriangle)); if(!model->triangleArray) { pgeFree(model->vertexArray); pgeFree(model->normalArray); pgeFree(model->texCoordArray); pgeFree(model); return NULL; } } // Read from the start of the file again and fill our arrays currentpos = buffer; unsigned int currentcolor = 0xFFFFFFFF; float tempnv = 0.0f; while(currentpos != endpos) { position = 0; while((isdeadspace(*currentpos)) && (currentpos != endpos)) currentpos++; while((!iseol(*currentpos)) && (currentpos != endpos) && (position < 512)) { readbuffer[position++] = *currentpos; currentpos++; } readbuffer[position] = 0; if(strequal(readbuffer, "vn", &readbuffer[position], 2)) { sscanf(readbuffer, "vn %f %f %f", &model->normalArray[normalpos].x, &model->normalArray[normalpos].y, &model->normalArray[normalpos].z); normalpos++; } else if(strequal(readbuffer, "vt", &readbuffer[position], 2)) { sscanf(readbuffer, "vt %f %f", &model->texCoordArray[texvertpos].u, &model->texCoordArray[texvertpos].v); texvertpos++; } else if(strequal(readbuffer, "v", &readbuffer[position], 1)) { sscanf(readbuffer, "v %f %f %f", &model->vertexArray[vertpos].x, &model->vertexArray[vertpos].y, &model->vertexArray[vertpos].z); vertpos++; } else if(strequal(readbuffer, "f", &readbuffer[position], 1)) { if(model->numMaterial > 0) model->triangleArray[facepos].color = currentcolor; if(model->numTexCoord > 0 && model->numNormal > 0) { sscanf(readbuffer, "f %d/%d/%d %d/%d/%d %d/%d/%d", &model->triangleArray[facepos].vertex[0], &model->triangleArray[facepos].texcoord[0], &model->triangleArray[facepos].normal[0], &model->triangleArray[facepos].vertex[1], &model->triangleArray[facepos].texcoord[1], &model->triangleArray[facepos].normal[1], &model->triangleArray[facepos].vertex[2], &model->triangleArray[facepos].texcoord[2], &model->triangleArray[facepos].normal[2]); facepos++; } else if(model->numNormal > 0) { sscanf(readbuffer, "f %d//%d %d//%d %d//%d", &model->triangleArray[facepos].vertex[0], &model->triangleArray[facepos].normal[0], &model->triangleArray[facepos].vertex[1], &model->triangleArray[facepos].normal[1], &model->triangleArray[facepos].vertex[2], &model->triangleArray[facepos].normal[2]); facepos++; } else if(model->numTexCoord > 0) { sscanf(readbuffer, "f %d/%d %d/%d %d/%d", &model->triangleArray[facepos].vertex[0], &model->triangleArray[facepos].texcoord[0], &model->triangleArray[facepos].vertex[1], &model->triangleArray[facepos].texcoord[1], &model->triangleArray[facepos].vertex[2], &model->triangleArray[facepos].texcoord[2]); facepos++; } else { sscanf(readbuffer, "f %d %d %d", &model->triangleArray[facepos].vertex[0], &model->triangleArray[facepos].vertex[1], &model->triangleArray[facepos].vertex[2]); facepos++; } } else if(strequal(readbuffer, "mtllib", &readbuffer[position], 6)) { sscanf(readbuffer, "mtllib %s", materialname); mtl = pgeObjLoadMaterial(materialname); if(!mtl) { pgeFree(model->vertexArray); pgeFree(model->normalArray); pgeFree(model->texCoordArray); pgeFree(model); return NULL; } } else if(strequal(readbuffer, "usemtl", &readbuffer[position], 6)) { sscanf(readbuffer, "usemtl %s", materialname); currentcolor = pgeObjSetColorFromMaterial(mtl, materialname); } } pgeObj *obj = (pgeObj *)pgeMalloc(sizeof(pgeObj)); if(!obj) { pgeFree(model->vertexArray); pgeFree(model->normalArray); pgeFree(model->texCoordArray); pgeFree(model->triangleArray); pgeFree(model); return NULL; } memset(obj, 0, sizeof(obj)); // Arrange the data into our vert array. obj->numvertices = model->numTriangle * 3; int i = 0; int f = 0; int v = 0; if(model->numTexCoord > 0 && model->numNormal > 0) { if(model->numMaterial == 0) { obj->vertices = (pgeVertTNV *)pgeMalloc(sizeof(pgeVertTNV) * model->numTriangle * 3); pgeVertTNV *ptr = (pgeVertTNV *)obj->vertices; obj->drawflag = GU_TEXTURE_32BITF|GU_NORMAL_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].u = model->texCoordArray[model->triangleArray[i].texcoord[f]-1].u; ptr[v].v = 1.0f - model->texCoordArray[model->triangleArray[i].texcoord[f]-1].v; ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; tempnv = 1.0f/(pgeMathSqrt(ptr[v].x*ptr[v].x + ptr[v].y*ptr[v].y + ptr[v].z*ptr[v].z)); ptr[v].nx = ptr[v].x * tempnv; ptr[v].ny = ptr[v].y * tempnv; ptr[v].nz = ptr[v].z * tempnv; v++; } } } else { obj->vertices = (pgeVertTCNV *)pgeMalloc(sizeof(pgeVertTCNV) * model->numTriangle * 3); pgeVertTCNV *ptr = (pgeVertTCNV *)obj->vertices; obj->drawflag = GU_COLOR_8888|GU_TEXTURE_32BITF|GU_NORMAL_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].u = model->texCoordArray[model->triangleArray[i].texcoord[f]-1].u; ptr[v].v = 1.0f - model->texCoordArray[model->triangleArray[i].texcoord[f]-1].v; ptr[v].color = model->triangleArray[i].color; ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; tempnv = 1.0f/(pgeMathSqrt(ptr[v].x*ptr[v].x + ptr[v].y*ptr[v].y + ptr[v].z*ptr[v].z)); ptr[v].nx = ptr[v].x * tempnv; ptr[v].ny = ptr[v].y * tempnv; ptr[v].nz = ptr[v].z * tempnv; v++; } } } } else if(model->numTexCoord > 0) { if(model->numMaterial == 0) { obj->vertices = (pgeVertTV *)pgeMalloc(sizeof(pgeVertTV) * model->numTriangle * 3); pgeVertTV *ptr = (pgeVertTV *)obj->vertices; obj->drawflag = GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].u = model->texCoordArray[model->triangleArray[i].texcoord[f]-1].u; ptr[v].v = 1.0f - model->texCoordArray[model->triangleArray[i].texcoord[f]-1].v; ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; v++; } } } else { obj->vertices = (pgeVertTCV *)pgeMalloc(sizeof(pgeVertTCV) * model->numTriangle * 3); pgeVertTCV *ptr = (pgeVertTCV *)obj->vertices; obj->drawflag = GU_COLOR_8888|GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].u = model->texCoordArray[model->triangleArray[i].texcoord[f]-1].u; ptr[v].v = 1.0f - model->texCoordArray[model->triangleArray[i].texcoord[f]-1].v; ptr[v].color = model->triangleArray[i].color; ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; v++; } } } } else if(model->numNormal > 0) { if(model->numMaterial == 0) { obj->vertices = (pgeVertNV *)pgeMalloc(sizeof(pgeVertNV) * model->numTriangle * 3); pgeVertNV *ptr = (pgeVertNV *)obj->vertices; obj->drawflag = GU_NORMAL_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; tempnv = 1.0f/(pgeMathSqrt(ptr[v].x*ptr[v].x + ptr[v].y*ptr[v].y + ptr[v].z*ptr[v].z)); ptr[v].nx = ptr[v].x * tempnv; ptr[v].ny = ptr[v].y * tempnv; ptr[v].nz = ptr[v].z * tempnv; v++; } } } else { obj->vertices = (pgeVertCNV *)pgeMalloc(sizeof(pgeVertCNV) * model->numTriangle * 3); pgeVertCNV *ptr = (pgeVertCNV *)obj->vertices; obj->drawflag = GU_COLOR_8888|GU_NORMAL_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].color = model->triangleArray[i].color; ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; tempnv = 1.0f/(pgeMathSqrt(ptr[v].x*ptr[v].x + ptr[v].y*ptr[v].y + ptr[v].z*ptr[v].z)); ptr[v].nx = ptr[v].x * tempnv; ptr[v].ny = ptr[v].y * tempnv; ptr[v].nz = ptr[v].z * tempnv; v++; } } } } else { if(model->numMaterial == 0) { obj->vertices = (pgeVertV *)pgeMalloc(sizeof(pgeVertV) * model->numTriangle * 3); pgeVertV *ptr = (pgeVertV *)obj->vertices; obj->drawflag = GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; v++; } } } else { obj->vertices = (pgeVertCV *)pgeMalloc(sizeof(pgeVertCV) * model->numTriangle * 3); pgeVertCV *ptr = (pgeVertCV *)obj->vertices; obj->drawflag = GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D; for(i = 0; i < model->numTriangle;i++) { for(f = 0; f < 3;f++) { ptr[v].color = model->triangleArray[i].color; ptr[v].x = model->vertexArray[model->triangleArray[i].vertex[f]-1].x; ptr[v].y = model->vertexArray[model->triangleArray[i].vertex[f]-1].y; ptr[v].z = model->vertexArray[model->triangleArray[i].vertex[f]-1].z; v++; } } } } // Tidy up if(model->vertexArray) pgeFree(model->vertexArray); if(model->normalArray) pgeFree(model->normalArray); if(model->texCoordArray) pgeFree(model->texCoordArray); if(model->triangleArray) pgeFree(model->triangleArray); if(model) pgeFree(model); if(mtl) { for(i = 0;i < mtl->nummaterials;i++) { if(mtl->materials[i].name) pgeFree(mtl->materials[i].name); if(mtl->materials) pgeFree(mtl->materials); } pgeFree(mtl); } sceKernelDcacheWritebackInvalidateAll(); return obj; }
/* * Mangle the "Transport:" header: * - Replace all occurences of "client_port=<spec>" * - Handle destination parameter * * In: * ct, ctinfo = conntrack context * skb = packet * tranoff = Transport header offset from TCP data * tranlen = Transport header length (incl. CRLF) * rport_lo = replacement low port (host endian) * rport_hi = replacement high port (host endian) * * Returns packet size difference. * * Assumes that a complete transport header is present, ending with CR or LF */ static int rtsp_mangle_tran(enum ip_conntrack_info ctinfo, struct nf_conntrack_expect* exp, struct ip_ct_rtsp_expect* prtspexp, struct sk_buff* skb, uint tranoff, uint tranlen) { char* ptcp; uint tcplen; char* ptran; char rbuf1[16]; /* Replacement buffer (one port) */ uint rbuf1len; /* Replacement len (one port) */ char rbufa[16]; /* Replacement buffer (all ports) */ uint rbufalen; /* Replacement len (all ports) */ u_int32_t newip; u_int16_t loport, hiport; uint off = 0; uint diff; /* Number of bytes we removed */ struct nf_conn *ct = exp->master; struct nf_conntrack_tuple *t; char szextaddr[15+1]; uint extaddrlen; int is_stun; get_skb_tcpdata(skb, &ptcp, &tcplen); ptran = ptcp+tranoff; if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || tranlen < 10 || !iseol(ptran[tranlen-1]) || nf_strncasecmp(ptran, "Transport:", 10) != 0) { pr_info("sanity check failed\n"); return 0; } off += 10; SKIP_WSPACE(ptcp+tranoff, tranlen, off); newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; t = &exp->tuple; t->dst.u3.ip = newip; extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) : sprintf(szextaddr, "%pI4", &newip); pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); rbuf1len = rbufalen = 0; switch (prtspexp->pbtype) { case pb_single: for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ { t->dst.u.udp.port = htons(loport); if (nf_ct_expect_related(exp) == 0) { pr_debug("using port %hu\n", loport); break; } } if (loport != 0) { rbuf1len = sprintf(rbuf1, "%hu", loport); rbufalen = sprintf(rbufa, "%hu", loport); } break; case pb_range: for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */ { t->dst.u.udp.port = htons(loport); if (nf_ct_expect_related(exp) == 0) { hiport = loport + 1; //~exp->mask.dst.u.udp.port; pr_debug("using ports %hu-%hu\n", loport, hiport); break; } } if (loport != 0) { rbuf1len = sprintf(rbuf1, "%hu", loport); rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1); } break; case pb_discon: for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ { t->dst.u.udp.port = htons(loport); if (nf_ct_expect_related(exp) == 0) { pr_debug("using port %hu (1 of 2)\n", loport); break; } } for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */ { t->dst.u.udp.port = htons(hiport); if (nf_ct_expect_related(exp) == 0) { pr_debug("using port %hu (2 of 2)\n", hiport); break; } } if (loport != 0 && hiport != 0) { rbuf1len = sprintf(rbuf1, "%hu", loport); if (hiport == loport+1) { rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); } else { rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport); } } break; } if (rbuf1len == 0) { return 0; /* cannot get replacement port(s) */ } /* Transport: tran;field;field=val,tran;field;field=val,... */ while (off < tranlen) { uint saveoff; const char* pparamend; uint nextparamoff; pparamend = memchr(ptran+off, ',', tranlen-off); pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; nextparamoff = pparamend-ptcp; /* * We pass over each param twice. On the first pass, we look for a * destination= field. It is handled by the security policy. If it * is present, allowed, and equal to our external address, we assume * that STUN is being used and we leave the client_port= field alone. */ is_stun = 0; saveoff = off; while (off < nextparamoff) { const char* pfieldend; uint nextfieldoff; pfieldend = memchr(ptran+off, ';', nextparamoff-off); nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) { if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) { is_stun = 1; } if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { diff = nextfieldoff-off; if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, off, diff, NULL, 0)) { /* mangle failed, all we can do is bail */ nf_ct_unexpect_related(exp); return 0; } get_skb_tcpdata(skb, &ptcp, &tcplen); ptran = ptcp+tranoff; tranlen -= diff; nextparamoff -= diff; nextfieldoff -= diff; } } off = nextfieldoff; } if (is_stun) { continue; } off = saveoff; while (off < nextparamoff) { const char* pfieldend; uint nextfieldoff; pfieldend = memchr(ptran+off, ';', nextparamoff-off); nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; if (strncmp(ptran+off, "client_port=", 12) == 0) { u_int16_t port; uint numlen; uint origoff; uint origlen; char* rbuf = rbuf1; uint rbuflen = rbuf1len; off += 12; origoff = (ptran-ptcp)+off; origlen = 0; numlen = nf_strtou16(ptran+off, &port); off += numlen; origlen += numlen; if (port != prtspexp->loport) { pr_debug("multiple ports found, port %hu ignored\n", port); } else { if (ptran[off] == '-' || ptran[off] == '/') { off++; origlen++; numlen = nf_strtou16(ptran+off, &port); off += numlen; origlen += numlen; rbuf = rbufa; rbuflen = rbufalen; } /* * note we cannot just memcpy() if the sizes are the same. * the mangle function does skb resizing, checks for a * cloned skb, and updates the checksums. * * parameter 4 below is offset from start of tcp data. */ diff = origlen-rbuflen; if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, origoff, origlen, rbuf, rbuflen)) { /* mangle failed, all we can do is bail */ nf_ct_unexpect_related(exp); return 0; } get_skb_tcpdata(skb, &ptcp, &tcplen); ptran = ptcp+tranoff; tranlen -= diff; nextparamoff -= diff; nextfieldoff -= diff; } } off = nextfieldoff; } off = nextparamoff; } return 1; }
/** * Parse (and execute) new macro definition. * @param mb macro expansion state * @param se macro definition to parse * @param level macro recursion level * @param expandbody should body be expanded? * @return address to continue parsing */ static const char * doDefine(MacroBuf mb, const char * se, int level, int expandbody) { const char *s = se; size_t blen = MACROBUFSIZ; char *buf = xmalloc(blen); char *n = buf, *ne = n; char *o = NULL, *oe; char *b, *be; int c; int oc = ')'; /* Copy name */ COPYNAME(ne, s, c); /* Copy opts (if present) */ oe = ne + 1; if (*s == '(') { s++; /* skip ( */ o = oe; COPYOPTS(oe, s, oc); s++; /* skip ) */ } /* Copy body, skipping over escaped newlines */ b = be = oe + 1; SKIPBLANK(s, c); if (c == '{') { /* XXX permit silent {...} grouping */ if ((se = matchchar(s, c, '}')) == NULL) { rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated body\n"), n); se = s; /* XXX W2DO? */ return se; } s++; /* XXX skip { */ strncpy(b, s, (se - s)); b[se - s] = '\0'; be += strlen(b); se++; /* XXX skip } */ s = se; /* move scan forward */ } else { /* otherwise free-field */ int bc = 0, pc = 0; while (*s && (bc || pc || !iseol(*s))) { switch (*s) { case '\\': switch (*(s+1)) { case '\0': break; default: s++; break; } break; case '%': switch (*(s+1)) { case '{': *be++ = *s++; bc++; break; case '(': *be++ = *s++; pc++; break; case '%': *be++ = *s++; break; } break; case '{': if (bc > 0) bc++; break; case '}': if (bc > 0) bc--; break; case '(': if (pc > 0) pc++; break; case ')': if (pc > 0) pc--; break; } *be++ = *s++; } *be = '\0'; if (bc || pc) { rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated body\n"), n); se = s; /* XXX W2DO? */ return se; } /* Trim trailing blanks/newlines */ while (--be >= b && (c = *be) && (isblank(c) || iseol(c))) {}; *(++be) = '\0'; /* one too far */ } /* Move scan over body */ while (iseol(*s)) s++; se = s; /* Names must start with alphabetic or _ and be at least 3 chars */ if (!((c = *n) && (risalpha(c) || c == '_') && (ne - n) > 2)) { rpmlog(RPMLOG_ERR, _("Macro %%%s has illegal name (%%define)\n"), n); return se; } /* Options must be terminated with ')' */ if (o && oc != ')') { rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated opts\n"), n); goto exit; } if ((be - b) < 1) { rpmlog(RPMLOG_ERR, _("Macro %%%s has empty body\n"), n); goto exit; } if (expandbody && expandU(mb, b, (&buf[blen] - b))) { rpmlog(RPMLOG_ERR, _("Macro %%%s failed to expand\n"), n); goto exit; } addMacro(mb->mc, n, o, b, (level - 1)); exit: _free(buf); return se; }
/** * The main macro recursion loop. * @todo Dynamically reallocate target buffer. * @param mb macro expansion state * @return 0 on success, 1 on failure */ static int expandMacro(MacroBuf mb) { rpmMacroEntry *mep; rpmMacroEntry me; const char *s = mb->s, *se; const char *f, *fe; const char *g, *ge; size_t fn, gn; char *t = mb->t; /* save expansion pointer for printExpand */ int c; int rc = 0; int negate; const char * lastc; int chkexist; if (++mb->depth > max_macro_depth) { rpmlog(RPMLOG_ERR, _("Recursion depth(%d) greater than max(%d)\n"), mb->depth, max_macro_depth); mb->depth--; mb->expand_trace = 1; return 1; } while (rc == 0 && mb->nb > 0 && (c = *s) != '\0') { s++; /* Copy text until next macro */ switch(c) { case '%': if (*s) { /* Ensure not end-of-string. */ if (*s != '%') break; s++; /* skip first % in %% */ } default: SAVECHAR(mb, c); continue; break; } /* Expand next macro */ f = fe = NULL; g = ge = NULL; if (mb->depth > 1) /* XXX full expansion for outermost level */ t = mb->t; /* save expansion pointer for printExpand */ negate = 0; lastc = NULL; chkexist = 0; switch ((c = *s)) { default: /* %name substitution */ while (strchr("!?", *s) != NULL) { switch(*s++) { case '!': negate = ((negate + 1) % 2); break; case '?': chkexist++; break; } } f = se = s; if (*se == '-') se++; while((c = *se) && (risalnum(c) || c == '_')) se++; /* Recognize non-alnum macros too */ switch (*se) { case '*': se++; if (*se == '*') se++; break; case '#': se++; break; default: break; } fe = se; /* For "%name " macros ... */ if ((c = *fe) && isblank(c)) if ((lastc = strchr(fe,'\n')) == NULL) lastc = strchr(fe, '\0'); break; case '(': /* %(...) shell escape */ if ((se = matchchar(s, c, ')')) == NULL) { rpmlog(RPMLOG_ERR, _("Unterminated %c: %s\n"), (char)c, s); rc = 1; continue; } if (mb->macro_trace) printMacro(mb, s, se+1); s++; /* skip ( */ rc = doShellEscape(mb, s, (se - s)); se++; /* skip ) */ s = se; continue; break; case '{': /* %{...}/%{...:...} substitution */ if ((se = matchchar(s, c, '}')) == NULL) { rpmlog(RPMLOG_ERR, _("Unterminated %c: %s\n"), (char)c, s); rc = 1; continue; } f = s+1;/* skip { */ se++; /* skip } */ while (strchr("!?", *f) != NULL) { switch(*f++) { case '!': negate = ((negate + 1) % 2); break; case '?': chkexist++; break; } } for (fe = f; (c = *fe) && !strchr(" :}", c);) fe++; switch (c) { case ':': g = fe + 1; ge = se - 1; break; case ' ': lastc = se-1; break; default: break; } break; } /* XXX Everything below expects fe > f */ fn = (fe - f); gn = (ge - g); if ((fe - f) <= 0) { /* XXX Process % in unknown context */ c = '%'; /* XXX only need to save % */ SAVECHAR(mb, c); #if 0 rpmlog(RPMLOG_ERR, _("A %% is followed by an unparseable macro\n")); #endif s = se; continue; } if (mb->macro_trace) printMacro(mb, s, se); /* Expand builtin macros */ if (STREQ("global", f, fn)) { s = doDefine(mb, se, RMIL_GLOBAL, 1); continue; } if (STREQ("define", f, fn)) { s = doDefine(mb, se, mb->depth, 0); continue; } if (STREQ("undefine", f, fn)) { s = doUndefine(mb->mc, se); continue; } if (STREQ("echo", f, fn) || STREQ("warn", f, fn) || STREQ("error", f, fn)) { int waserror = 0; if (STREQ("error", f, fn)) waserror = 1; if (g != NULL && g < ge) doOutput(mb, waserror, g, gn); else doOutput(mb, waserror, f, fn); s = se; continue; } if (STREQ("trace", f, fn)) { /* XXX TODO restore expand_trace/macro_trace to 0 on return */ mb->expand_trace = mb->macro_trace = (negate ? 0 : mb->depth); if (mb->depth == 1) { print_macro_trace = mb->macro_trace; print_expand_trace = mb->expand_trace; } s = se; continue; } if (STREQ("dump", f, fn)) { rpmDumpMacroTable(mb->mc, NULL); while (iseol(*se)) se++; s = se; continue; } #ifdef WITH_LUA if (STREQ("lua", f, fn)) { rpmlua lua = NULL; /* Global state. */ const char *ls = s+sizeof("{lua:")-1; const char *lse = se-sizeof("}")+1; char *scriptbuf = (char *)xmalloc((lse-ls)+1); const char *printbuf; memcpy(scriptbuf, ls, lse-ls); scriptbuf[lse-ls] = '\0'; rpmluaSetPrintBuffer(lua, 1); if (rpmluaRunScript(lua, scriptbuf, NULL) == -1) rc = 1; printbuf = rpmluaGetPrintBuffer(lua); if (printbuf) { size_t len = strlen(printbuf); if (len > mb->nb) len = mb->nb; memcpy(mb->t, printbuf, len); mb->t += len; mb->nb -= len; } rpmluaSetPrintBuffer(lua, 0); free(scriptbuf); s = se; continue; } #endif /* XXX necessary but clunky */ if (STREQ("basename", f, fn) || STREQ("suffix", f, fn) || STREQ("expand", f, fn) || STREQ("verbose", f, fn) || STREQ("uncompress", f, fn) || STREQ("url2path", f, fn) || STREQ("u2p", f, fn) || STREQ("getenv", f, fn) || STREQ("S", f, fn) || STREQ("P", f, fn) || STREQ("F", f, fn)) { /* FIX: verbose may be set */ doFoo(mb, negate, f, fn, g, gn); s = se; continue; } /* Expand defined macros */ mep = findEntry(mb->mc, f, fn); me = (mep ? *mep : NULL); /* XXX Special processing for flags */ if (*f == '-') { if (me) me->used++; /* Mark macro as used */ if ((me == NULL && !negate) || /* Without -f, skip %{-f...} */ (me != NULL && negate)) { /* With -f, skip %{!-f...} */ s = se; continue; } if (g && g < ge) { /* Expand X in %{-f:X} */ rc = expandT(mb, g, gn); } else if (me && me->body && *me->body) {/* Expand %{-f}/%{-f*} */ rc = expandT(mb, me->body, strlen(me->body)); } s = se; continue; } /* XXX Special processing for macro existence */ if (chkexist) { if ((me == NULL && !negate) || /* Without -f, skip %{?f...} */ (me != NULL && negate)) { /* With -f, skip %{!?f...} */ s = se; continue; } if (g && g < ge) { /* Expand X in %{?f:X} */ rc = expandT(mb, g, gn); } else if (me && me->body && *me->body) { /* Expand %{?f}/%{?f*} */ rc = expandT(mb, me->body, strlen(me->body)); } s = se; continue; } if (me == NULL) { /* leave unknown %... as is */ #ifndef HACK #if DEAD /* XXX hack to skip over empty arg list */ if (fn == 1 && *f == '*') { s = se; continue; } #endif /* XXX hack to permit non-overloaded %foo to be passed */ c = '%'; /* XXX only need to save % */ SAVECHAR(mb, c); #else rpmlog(RPMLOG_ERR, _("Macro %%%.*s not found, skipping\n"), fn, f); s = se; #endif continue; } /* Setup args for "%name " macros with opts */ if (me && me->opts != NULL) { if (lastc != NULL) { se = grabArgs(mb, me, fe, lastc); } else { addMacro(mb->mc, "**", NULL, "", mb->depth); addMacro(mb->mc, "*", NULL, "", mb->depth); addMacro(mb->mc, "#", NULL, "0", mb->depth); addMacro(mb->mc, "0", NULL, me->name, mb->depth); } } /* Recursively expand body of macro */ if (me->body && *me->body) { mb->s = me->body; rc = expandMacro(mb); if (rc == 0) me->used++; /* Mark macro as used */ } /* Free args for "%name " macros with opts */ if (me->opts != NULL) freeArgs(mb); s = se; } *mb->t = '\0'; mb->s = s; mb->depth--; if (rc != 0 || mb->expand_trace) printExpansion(mb, t, mb->t); return rc; }
int include(const char *filename) { struct includeline *script, *se, *sp; char input[256]; /* big enough? */ int argc,res; char **argv, *cp; int fd, flags, line; if (((fd = rel_open(filename, NULL, O_RDONLY)) == -1)) { command_errmsg = command_errbuf; snprintf(command_errbuf, 256, "cannot find \"%s\"", filename); return(CMD_ERROR); } /* * Read the script into memory. */ script = se = NULL; line = 0; while (fgets(input, sizeof(input), fd) != NULL) { line++; flags = 0; if(strlen(input) == sizeof(input) - 1 && !iseol(input[sizeof(input) - 2])) { printf("WARNING: %s: %s: Line too long: truncating; have:\n", __func__, filename); printf("%s\n", input); skipeol(fd); } /* Discard comments */ if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0) continue; cp = input; /* Echo? */ if (input[0] == '@') { cp++; flags |= SL_QUIET; } /* Error OK? */ if (input[0] == '-') { cp++; flags |= SL_IGNOREERR; } /* Allocate script line structure and copy line, flags */ sp = malloc(sizeof(struct includeline) + strlen(cp) + 1); sp->text = (char *)sp + sizeof(struct includeline); strcpy(sp->text, cp); sp->flags = flags; sp->line = line; sp->next = NULL; if (script == NULL) { script = sp; } else { se->next = sp; } se = sp; } close(fd); /* * Execute the script */ argv = NULL; res = CMD_OK; for (sp = script; sp != NULL; sp = sp->next) { #if 0 /* print if not being quiet */ if (!(sp->flags & SL_QUIET)) { prompt(); printf("%s\n", sp->text); } #endif /* Parse the command */ if (!parse(&argc, &argv, sp->text)) { if ((argc > 0) && (perform(argc, argv) != 0)) { /* normal command */ printf("%s: %s\n", argv[0], command_errmsg); if (!(sp->flags & SL_IGNOREERR)) { res=CMD_ERROR; break; } } free(argv); argv = NULL; } else { printf("%s line %d: parse error\n", filename, sp->line); res=CMD_ERROR; break; } } if (argv != NULL) free(argv); while(script != NULL) { se = script; script = script->next; free(se); } return(res); }
CC_STRING CMaExpander::Expand_FLM(CMacro *ma) { CC_STRING outs; CC_ARRAY<CC_STRING> margs; CC_STRING carg; const char *p = pos; int level; skip_blanks(p); if( iseol(*p) ) { gex.format("Macro \"%s\" expects arguments", TR(tc,ma->id)); throw &gex; } if( *p != '(' ) { gex = "Macro expects '('"; throw &gex; } p++; skip_blanks(p); level = 1; while( 1 ) { if( iseol(*p) ) break; if( *p == ',' ) { if( level == 1 && ( ! ma->va_args || (margs.size() + 1 < ma->nr_args) ) ) { Trim(carg); margs.push_back(carg); carg.clear(); } else { carg += ','; skip_blanks(p); } } else if(*p == '(') { level ++; carg += '('; } else if(*p == ')') { level --; if(level == 0) { p++; Trim(carg); margs.push_back(carg); carg.clear(); break; } else carg += ')'; } else { carg += *p; } p++; } pos = p; XCHAR *xc; CC_STRING s; size_t n; n = ma->nr_args; assert(n != CMacro::OL_M); if(n != margs.size()) { if( ma->va_args && margs.size() + 1 == n ) { margs.push_back(CC_STRING("")); } else { gex.format("Macro \"%s\" requires %u arguments, but %u given", TR(tc,ma->id), n, margs.size() ); throw &gex; } } for(xc = ma->parsed; *xc != 0; xc++) { if(IS_MA_PAR2(*xc) || IS_MA_PAR0(*xc)) { const CC_STRING& carg = margs[(uint8_t)*xc]; CMaExpander expander2(tc, carg.c_str(), for_include); CC_STRING tmp; tmp = expander2.TryExpand(); s += tmp; } else if(IS_MA_PAR1(*xc)) { const CC_STRING& carg = margs[(uint8_t)*xc]; s += '"'; s += carg; s += '"'; } else { s += (char) *xc; } } outs += s; return outs; }
/* * Find lo/hi client ports (if any) in transport header * In: * ptcp, tcplen = packet * tranoff, tranlen = buffer to search * * Out: * pport_lo, pport_hi = lo/hi ports (host endian) * * Returns nonzero if any client ports found * * Note: it is valid (and expected) for the client to request multiple * transports, so we need to parse the entire line. */ static int rtsp_parse_transport(char* ptran, uint tranlen, struct ip_ct_rtsp_expect* prtspexp) { int rc = 0; uint off = 0; if (tranlen < 10 || !iseol(ptran[tranlen-1]) || nf_strncasecmp(ptran, "Transport:", 10) != 0) { pr_info("sanity check failed\n"); return 0; } pr_debug("tran='%.*s'\n", (int)tranlen, ptran); off += 10; SKIP_WSPACE(ptran, tranlen, off); /* Transport: tran;field;field=val,tran;field;field=val,... */ while (off < tranlen) { const char* pparamend; uint nextparamoff; pparamend = memchr(ptran+off, ',', tranlen-off); pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; nextparamoff = pparamend-ptran; while (off < nextparamoff) { const char* pfieldend; uint nextfieldoff; pfieldend = memchr(ptran+off, ';', nextparamoff-off); nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; if (strncmp(ptran+off, "client_port=", 12) == 0) { u_int16_t port; uint numlen; off += 12; numlen = nf_strtou16(ptran+off, &port); off += numlen; if (prtspexp->loport != 0 && prtspexp->loport != port) pr_debug("multiple ports found, port %hu ignored\n", port); else { pr_debug("lo port found : %hu\n", port); prtspexp->loport = prtspexp->hiport = port; if (ptran[off] == '-') { off++; numlen = nf_strtou16(ptran+off, &port); off += numlen; prtspexp->pbtype = pb_range; prtspexp->hiport = port; // If we have a range, assume rtp: // loport must be even, hiport must be loport+1 if ((prtspexp->loport & 0x0001) != 0 || prtspexp->hiport != prtspexp->loport+1) { pr_debug("incorrect range: %hu-%hu, correcting\n", prtspexp->loport, prtspexp->hiport); prtspexp->loport &= 0xfffe; prtspexp->hiport = prtspexp->loport+1; } } else if (ptran[off] == '/') { off++; numlen = nf_strtou16(ptran+off, &port); off += numlen; prtspexp->pbtype = pb_discon; prtspexp->hiport = port; } rc = 1; } } /* * Note we don't look for the destination parameter here. * If we are using NAT, the NAT module will handle it. If not, * and the client is sending packets elsewhere, the expectation * will quietly time out. */ off = nextfieldoff; } off = nextparamoff; } return rc; }
static void handle_define(TCC_CONTEXT *tc, sym_t mid, CMacro *ma) { enum { STA_OKAY, STA_LEFT_PARENTHESIS, STA_PARAMETER, STA_SEPERATOR, STA_TRIDOT, } state; const char *line = ma->line; CToken token; if( ! get_token(tc, &line, &token, false) ) return; if(token.attr == CToken::TA_IDENT) { if(*line == '(') { CC_ARRAY<sym_t> para_list; XCHAR *xc; const char *last_pos; sym_t last_para = SSID_INVALID; bool has_va_args = false; state = STA_LEFT_PARENTHESIS; line++; while( get_token(tc, &line, &token, false) ) { switch(state) { case STA_LEFT_PARENTHESIS: if( token.id == SSID_RIGHT_PARENTHESIS) { state = STA_OKAY; goto okay; } else if(token.attr == CToken::TA_IDENT) { para_list.push_back(token.id); state = STA_SEPERATOR; } else if(token.id == SSID_TRIDOT) { state = STA_TRIDOT; continue; } else { gEx.format("\"%s\" may not appear in macro parameter list", TR(tc,token.id)); goto error; } break; case STA_SEPERATOR: if(token.id == SSID_RIGHT_PARENTHESIS) { state = STA_OKAY; goto okay; } else if(token.id == SSID_COMMA) state = STA_PARAMETER; else if(token.id == SSID_TRIDOT) { state = STA_TRIDOT; } else { gEx = "macro parameters must be comma-separated"; goto error; } break; case STA_PARAMETER: if(token.id == SSID_TRIDOT) { state = STA_TRIDOT; continue; } else if(token.attr == CToken::TA_IDENT) { para_list.push_back(token.id); state = STA_SEPERATOR; } else { gEx = "parameter name missing"; goto error; } break; case STA_TRIDOT: if(token.id != SSID_RIGHT_PARENTHESIS) { gEx = "missing ')' in macro parameter list"; throw &gEx; } has_va_args = true; if(last_para == SSID_COMMA || last_para == SSID_LEFT_PARENTHESIS) { para_list.push_back(SSID_VA_ARGS); last_para = SSID_VA_ARGS; } goto okay; default: assert(0); } last_para = token.id; } if(state != STA_OKAY) { gEx = "missing ')' in macro parameter list"; throw &gEx; } okay: xc = (XCHAR*) malloc(sizeof(XCHAR) * strlen(line) + 4); ma->id = mid; ma->parsed = xc; ma->nr_args = para_list.size(); ma->va_args = has_va_args; skip_blanks(line); last_pos = line; sym_t prev_sid = SSID_INVALID; while( ReadToken(tc, &line, &token, &gEx, false) ) { if(gEx.GetError() != NULL) throw (&gEx); if(token.id == SSID_DUAL_SHARP) { if(xc == ma->parsed) { gEx = "'##' cannot appear at either end of a macro expansion"; goto error; } else if( IS_MA_PAR0(*(xc-1)) ) *(xc-1) |= XF_MA_PAR2; } if(prev_sid == SSID_DUAL_SHARP) { XCHAR *yc = xc - 3; while( yc >= ma->parsed && (*yc == '\t' || *yc == ' ') ) yc--; xc = yc + 1; assert(*xc == '#' || *xc == ' ' || *xc == '\t'); } if( token.attr == CToken::TA_IDENT ) { int magic = 0; int16_t para_ord; static const XCHAR xflags[3] = { XF_MA_PAR0, XF_MA_PAR1, XF_MA_PAR2 }; if( has_va_args && (token.id == last_para || token.id == SSID_VA_ARGS) ) para_ord = ma->nr_args - 1; else para_ord = find(token.id, para_list); if(prev_sid == SSID_SHARP) { if(para_ord < 0) { gEx = "'#' is not followed by a macro parameter"; goto error; } magic = 1; xc--; } else if(prev_sid == SSID_DUAL_SHARP) { magic = 2; } if(para_ord < 0) goto do_cat; *xc++ = para_ord | xflags[magic]; } else { do_cat: if(prev_sid == SSID_DUAL_SHARP) { skip_blanks(last_pos); } join(&xc, last_pos, line); } last_pos = line; prev_sid = token.id; } /*end while*/ *xc = 0; } else { XCHAR *xc; xc = (XCHAR*) malloc(sizeof(XCHAR) * strlen(line) + 4); ma->id = mid; ma->parsed = xc; ma->nr_args = CMacro::OL_M; skip_blanks(line); while(1) { char c = *line; if( iseol(c) ) { *xc = '\0'; break; } *xc = c; xc++, line++; } } } // dump(ma->parsed); return; error: throw &gEx; }